SQL注入绕过姿势总结
本文最后更新于:几秒前
一、大小写绕过
用于过滤时没有考虑到匹配大小写的情况:SeleCT * from table
二、 双写绕过
用于将禁止的字符直接替换删除的情况:
比如,使用preg_replace()
或者是str_replace()
将and
、or
、select
、union
等关键词替换为空字符串。
这时,可以使用双写嵌套绕过,or
写成oorr
,and
写成aandnd
、select
写成seselectlect
、union
写成uniunionon
。在删除一个关键字后,剩下的部分又可以重新组合成完整的关键字。
三、 内联注释
内联注释的作用是增加SQL语句的可移植性。比如,将MySQL特有的语法使用内联注释的形式来编写,在这种情况下,MySQL可以正常的解析并执行内联注释中的代码,但是其它的SQL服务器则忽略内联注释中的内容。/*! MySQL特有的语法 */
例如MySQL服务器可以在以下语句中识别STRAIGHT_JOIN
关键字,而其他服务器则不能:SELECT /*! STRAIGHT_JOIN*/ col1 FROM table1,table2 WHERE ...
如果在!后面添加版本号,则仅当MySQL版本大于或者等于指定的版本号时,才会执行注释中的语法。例如,以下注释中的关键字KEY_BLOCK_SIZE
仅由MySQL 5.1.10或者更高版本的服务器执行:CREATE TABLE t1(a INT, KEY (a)) /*!50110 KEY_BLOCK_SIZE=1024*/
/*! */
类型的注释,内部语句会被执行select bbb from table1 where aaa='' union /*! select database()*/;
可以用来绕过一些WAF,或者是绕过空格
但是,不能将关键词用注释分开,例如下面的语句是不可执行的(或者说只能在某些较老版本执行)select bbb from table1 where balabala='' union se/*!lect database()*/;
四、 使用16进制绕过特定字符
如果在查询字段名的时候表名被过滤,或者是数据库中某些特定字符被过滤,则可以使用16进制绕过。
1 |
|
五、 宽字节注入
常用的URL编码:
AsciI值 | URL编码 |
---|---|
空白字符 | %5C |
‘ | %27 |
“ | %22 |
# | %23 |
& | %26 |
宽字节注入利用条件:
查询参数是被单引号包围的,传入的单引号又被转义符\
转义,如在后台数据库中对接收的参数使用addslashes()
、mysql_real_escape_string()
或者是其他转义函数 数据库的编码为GBK
概括的说,就是单引号被转义,但编码为GBK。
六、 使用Unicode编码
Unicode有所谓的标准编码和非标准编码,假设我们用的utf-8为标准编码那么西欧语系所使用的就是非标准编码。
常见的Unicode编码:
符号 | Unicode 编码 |
---|---|
单引号 | %u0027、%u02b9、%u02bc、%u02c8、%u2032、%uff07 |
空格 | %u0020、%uff00 |
左括号 | %u0028、%uff08 |
右括号 | %u0029、%uff09 |
使用样例:
?id=10%df\'%u0020AND 1=2#
SELECT 'Ä'='A'; #1
第一个样例,使用上述提到的宽字节绕过,比如单引号转义操作变成',那么就变成了�',�\构成了一个宽字节即Unicode字节,单引号可以正常使用。
第二个样例,使用的是两种不同编码的字符进行比较,由于Unicode 编码种类多,基于黑名单的过滤器可能无法处理,所以实现绕过。
七、 使用等价函数或者命令
有些函数或命令因关键字被检测出来而无法使用但是在很多情况下可以使用与之等价或类似的函数或命令替代其使用。
- 函数或变量
原函数 | 替代函数 |
---|---|
hex(),bin() | ascii() |
sleep() | benchmark() |
concat_ws() | group_concat() |
mid(),substr() | substring() |
@@user | user() |
@@datadir | datadir() |
- 符号
原符号 | 替代符号 |
---|---|
and | &&或者& |
or | || |
not | ! |
= | “<>”或like或rlike |
“ “ | /**/或Tab或回车键或%A0 |
- 生僻函数
MySQL/PostgreSQL支持XML函数。MySQL、PostgreSQL、Oracle它们都有许多自己的函数基于黑名单的filter要想涵盖这么多东西从实际上来说不太可能而且代价太大因此黑名单的确是更适合处理已知的情况。
八、 使用特殊符号
使用反引号`,例如select `version()`,可以用来过空格和正则,特殊情况下还可以将其做注释符用
使用”-+.”,select+id-1+1.from users; “+”是用于字符串连接的,”-“和”.”在此也用于连接,可以逃过空格和关键字过滤
@符号,select@^1.from users; @用于变量定义如@var_name,一个@表示用户定义,@@表示系统变量
关键字拆分,例如‘se’+‘le’+‘ct’ 或者 %S%E%L%E%C%T
九、 HTTP参数控制
这里HTTP参数控制除了对查询语句的参数进行篡改还包括HTTP方法、HTTP头的控制。
1. HTTP Parameter Polution
例如:/?id=1;select+1&id=2,3+from+users+where+id=1—
/?id=1unionselectpwdfromusers
HPP 又称为重复参数污染,简单来说就是相如?id=1&id=2&id=3
这种情况不同服务器处理方式不同。具体处理方式如下:
WEB 服务器 | 参数获取函数 | 获取到的参数 |
---|---|---|
PHP/Apache | $_GET(“parameter”) | LASTER |
JSP/Tomcat | Request.getParameter(“parameter”) | FIRST |
Perl(CGI)/Apache | Param(“parameter”) | FIRST |
Python/Apache | getvalue(“Parameter”) | ALL(LIST) |
ASP/IIS | Request.QueryString(“parameter”) | ALL(comma-delimited string) |
2. HTTP Paramater Fragment
这种方法是HTTP分割注入同CRLF略有相似之处
例如:/?a=1+unionselect+1,passfrom+users--+
select * from table where a=1 unionselect 1,passfrom users--+
上面两个示例发现和HPP最后一个示例很像,它们不同之处在于参数不一样,这里是在不同的参数之间进行分割,到了数据库执行查询时再合并语句。
十、缓冲区溢出攻击
缓冲区溢出是用于对付WAF在内的软件本身,有不少WAF是C语言写的而C语言自身没有缓冲区保护机制,因此如果WAF在处理测试向量时超出了其缓冲区长度就会引发bug从而实现绕过。
例如:?id=1 and (select 1)=(Select 0xA*1000)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
0xA*1000指0xA后面”A”重复1000次,一般来说对应用软件构成缓冲区溢出都需要较大的测试长度。