Abusing JSON-Based SQL to Bypass WAF

We discussed this vulnerability during Episode 175 on 12 December 2022

Two parts to the post the vulnerability is a simple SQL injection, URL data winds up in the query. Nothing too special there. First part of the post covers the exploit crafting as they deal with a few issues that make exploitation more challenging. The second part of the post is when they discover the WAF was blocking their exploit from landing on the cloud deployments of the application.

So the first part, they had a few challenges to figure out.

  1. The injection allowed them to do a union based injection but the injected rows had to be integers. They used string_to_array to turn their strings into an array (multiple rows) of integers that could just be returned. Which leads into the second problem
  2. The rows were returned in random order. The order was based on the order asynchronous tasks completed in, this meant their string that was turned into many rows would be shuffled around, They got around this by adding the row index multiplied by 1000 so it wouldn’t clobber the ascii value. Allowing their one integer to contain both the original ascii and the row index so the proper order could be retrieved.
  3. Performance limitations meant that doing exfiltrated a single-row at a time was not time-feasible and asking for too many rows would timeout. To get around this they used a larger, BIGINT type, and crammed multiple rows into it, bitshifting the values.

The second part of the post is the “universal” WAF bypass.

They had this fun exploit, it would land against on-premisis deployments of the application, it would not however land against the cloud hosted instances. this was because of the AWS WAF blocking the SQL injection payload.

In researching how the WAFs worked they wondered if there was any SQL syntax that the WAF wouldn’t pick up on, and here enters native JSON support within the major database systems. What they found is intriguing, by injecting a JSON operation in front of their more traditional SQL injection they could bypass the WAF. I’m not entirely sure why this works, the authors say doing so “ threw the WAF into a loop and allowed us to supply malicious SQLi payloads”. Regardless, the impact here is that JSON operators resulted in the syntax parsing either failing or otherwise being shutdown. Which is cool, and even more surprising that this worked against multiple WAFs.