Submitted by Felipe Costa and Ryan Barnett (SpiderLabs Research - ModSecurity Team)
Increasing Adoption of Dynamic Web Content
Since the number of applications that accept JSON input is growing, it is natural to expect that JSON will be also used to transport web application attacks payloads. This leads to the next logical question with regards to defense: Can your Web Application Firewall (WAF)understand JSON? These different web technologies are similar to verbal languages and WAFs need to be multi-lingual to correctly identify attacks and minimize false positives. It is for this reason that we have added JSON support to ModSecurity.
Side Note: Trustwave's WebDefend WAF Product has JSON support in the upcoming v7 release.
New JSON Parsing Support in ModSecurity
In the newest ModSecurity release (v2.8.0), we have added JSON request body parsing support. This means that ModSecurity will be able to validate the format and extract JSON content for inspection much in the same way that it handles XML request body content. Thanks goes out to our SpiderLabs Research colleague Ulisses Albuquerque who originally developed this functionality.
How does JSON parsing work?
ModSecurity will automatically parse the following two request body content-types with built-in request body parsers:
In addition, if the request body is XML, ModSecurity can be configured with the "requestBodyProcessor" ctl action to dynamically initiate the libxml2 library to parse the content. Similar to how we handle XML content, we have now added JSON request body parsing support with the YAJL (Yet Another JSON Library) package. Image 1 illustrates the new portion of modsecurity.conf-recommended, where the JSON parser is activated by the ctl action.
Image 1: Rule that trigger the JSON parser whenever the content is specified as "application/json".
The rule, illustrated in Image 1, tells ModSecurity that if the Content-Type is application/json, the JSON body processor should be activated. Once the parser is triggered it will process the JSON content (arrays and structures), and each value will be added to a key inside the standard ARGS collection. The ARGS_NAMES values are based on the JSON parameter names. Similar to how the XML processor allows for XPath variables to be defined, the JSON parser will create ARGS_NAMES values as a concatenation of all the structure names that a value belongs to, split by a "." (dot). Image 2 shows an example of a JSON content (Image 2.a) and its corresponding representation in ModSecurity's ARGS collection (Image 2.b).
Image 2: (a) JSON example, from RFC 4627. (b) Representation of ModSecurity's ARGS collection after JSON parsing.
Example Usage: SQL Injection Attack in JSON Content
Let's see how it looks when an attacker attempts to send an SQL Injection attack inside the JSON Image.IDs parameter payload. The raw JSON request body is illustrated in Image 3.
Image 3: Illustrates a request body in JSON format. (a) Illustrates an SQL injection attempt.
When ModSecurity starts the requestbody processing phase, the JSON will be parsed and the content of the debug log will be similar to what is shown in Image 4, note in 4.a the SQL command is stored into: ARGS:Images.IDs.
Image 4: ModSecurity debug log while parsing a JSON request body. (a) An SQL Injection command is stored under the key Image.IDs.
This data is now held within the ARGS collection and can be used by the existing rules. Image 5 is a snippet of the debug log file when ModSecurity uses the @detectSQLi operator against this JSON data.
Image 5: (a) libinjection matching a fingerprint in the target value. (b) ModSecurity Alert Message Data.
Malformed JSON Data
When attackers attempt to inject malicious payload into JSON content, it will often cause parsing errors. ModSecurity's JSON parser populates data in a "stream" fashion, so errors such as missing the last "}" (brackets) will not prevent ModSecurity from filling the ARGS collection. ModSecurity will fill the collection until an error is noticed. Therefore, it is also critical to check the content of the "REQBODY_ERROR" variable which will be set to "1" if there is a parser error such as an incomplete or mal-formed JSON content.
In ModSecurity recommended configuration file, there is a rule - similar to the one illustrated in the Image 6 - that will block requests if JSON parser fails. This very same rule is also used to block other parser errors such as multipart/request-data or even the XML parser.
Image 6: Illustrates the rule that can be used to prevent a request if there is an error when parsing its content.
It is important to block requests whenever ModSecurity parser fails. Depending on the tolerance of a given parser it may process an invalid content as valid, in other words, applications can receive content without ModSecurity inspection, leading the possibility of an attacker delivering malicious content. Image 7. Is a log snippet showing when the JSON parser detects an error. Image 7.a. Shows the error message.
Image 7: Log snippet showing a JSON parser error. (a) Contains the explanation why the JSON parser failed.
Having these rules in place will help to minimize the chance of a false negative/bypass if attackers are purposefully attempting to alter the JSON format to break parsing.
How to have JSON parser working?
The JSON parser feature is now considered stable and part of ModSecurity v2.8.0, which was recently released. For those who don't want to wait for distribution packages or our official releases, the code is always available in our Git repository:
Applications that utilize dynamic code such as JSON will continue to grow and therefore web security devices must keep pace with the changing landscape of web application development languages and technologies. We encourage the ModSecurity community to test out this new feature and let us know if there are any issues or recommendations for updates.