DEV Community

Cover image for Bypassing ModSecurity WAF
Philippe Arteau
Philippe Arteau

Posted on • Updated on • Originally published at blog.h3xstream.com

Bypassing ModSecurity WAF

Being able to bypass Web Application Firewall (WAF) depends on your knowledge about their behavior. Here is a cool technique that involve expressions that are ignored in MySQL SQL parser (MySQL <= 5.7). This post summarizes the impact on libinjection. The libinjection library is used by WAF such as ModSecurity and SignalScience. For more details on AWS Cloudfront impact, read the original GoSecure article.

Image description

Scientific expression in MySQL

When MySQL sees 1.e(abc), it will ignore the 1.e( portion because the following characters do not form a valid numeric value.

This behavior can be abused to fool libinjection tokenizer. Libinjection internally tokenizes the parameter and identifies contextual section types such as comments and strings. Libinjection sees the string “1.e” as an unknown SQL keyword and concludes that it is more likely to be an English sentence than code. When libinjection is unaware of an SQL function the same behavior can be exhibited.

Attack in action

Here is a demonstration of modsecurity’s capability to block a malicious pattern for SQL injection. A forbidden page is returned which is the consequence of detection.

SQL injection blocked

*Blocked!*

In the following image, you can see the original request being slightly modified to bypass modsecurity and libinjection.

SQL injection bypass WAF

*WAF Bypass!*

Complete payload

Now, how do we go beyond or 1=1 payloads? The NUMBER.e expression can be inserted at plenty of locations without breaking the SQL query. The following payload demonstrated read on arbitrary SQL tables.

' 1.e(ascii 1.e(substring(1.e(select password from users limit 1 1.e,1 1.e) 1.e,1 1.e,1 1.e)1.e)1.e) = 70 or'1'='2
Enter fullscreen mode Exit fullscreen mode

The same payload was indented below for readability. 1.e( and 1.e, are ignored from the parser.

1.e(ascii 
1.e(substring(
1.e(select password from users limit 1 1.e,1 1.e) 1.e,1 1.e,1 1.e)1.e)1.e) = 70 #(first char = 70)
or'1'='2
Enter fullscreen mode Exit fullscreen mode

Conclusion

Most bypass techniques evolve using special encoding to obfuscate the malicious requests (URL encoding, Unicode multibytes, XML entities, etc). This technique will work if the system behind the WAF is doing an unexpected decoding. This new technique is not encoding related. For this reason, it will be a versatile trick until most system upgrade their MySQL instances.

*Full story on [GoSecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/) (More details on AWS Cloudfront)*

Top comments (0)