OWASP ModSecurity Securing WebGoat Section4 Sublesson 03.5

3. AJAX Security -> 3.5 XML Injection

Lesson overview
The WebGoat lesson overview is included with the WebGoat lesson solution.

Lesson solution
Refer to the zip file with the WebGoat lesson solutions. See Appendix A for more information.

Strategy
This WebGoat lesson adds more rewards to the allowed set of rewards by intercepting an AJAX response and appending these 2 entries to the XML list: WebGoat Core Duo Laptop 2000 Pts WebGoat Hawaii Cruise 3000 Pts

However, the lesson is broke on the back end:

When rewards are selected, a POST is sent, for example: accountID=836239&check1001=on&check1002=on&check1003=on&SUBMIT=Submit

The problem is that there is no association between a checked entry, e.g. 'check1001' and a reward. This is because in the callback routine of the Ajax request, numbers are assigned irrespective of the reward: for(var i=0; i< rewards.length; i++){ strHTML = strHTML + ' 

To prove it, I did not add the 2 high-priced point rewards, I substituted them for the 't-shirt 50 Pts' and 'Secure Kettle 30 pts'; the return message should be:

The following items will be shipped to your address: WebGoat Core Duo Laptop WebGoat Hawaii Cruise WebGoat Mug

But the return message was erroneous:



(screenshot lesson03-5_rewards.jpg)

Therefore, since the rewards cannot be distinguished from each other, the only choice is to count the number of rewards sent, and if that doesn't match the number of rewards in the original HTTP response - before manipulation in the web proxy - then an error is thrown.

Implementation
The ModSecurity solution will be to count the number of rewards sent to the user in the response body, then compare that with the number of rewards that the user subsequently sends in the request.

Start the lesson with an empty data file 'lesson03-5.data' with the proper file permissions.

First, process the response body and persist the rewards list to the data file.

ModSecurity has to be configured to process XML; add 'text/xml' to the 'SecResponseBodyMimeType' directive in 'rulefile_00_phase2-initialize.conf': SecResponseBodyMimeType text/plain text/html text/xml

The phase 4 response portion of the configuration file is: SecRuleScript "/etc/modsecurity/data/rewards-response_03-5.lua" \ "phase:4,t:none,log,auditlog,allow,msg:'Luascript: \ AJAX Security -> 3.5 XML Injection: in RESPONSE; writing rewards to file'"

Refer to the Lua script 'rewards-response_03-5.lua'. The steps are:
 * read the response body into a buffer
 * extract each reward using the pattern ' (.-) '
 * write each reward to the data file

An example will look like: Entry{ reward = "WebGoat t-shirt 20 Pts" }

Entry{ reward = "WebGoat Secure Kettle 50 Pts" }

Entry{ reward = "WebGoat Mug 30 Pts" }

For phase 2, the POST request parameters have the form: accountID=836239&check1001=on&check1002=on&check1003=on&SUBMIT=Submit

The phase 2 request portion of the configuration file is: SecRule &ARGS_POST:SUBMIT "@eq 0" "nolog,skip:3" SecRule &ARGS_POST:accountID "@eq 0" "nolog,skip:2"

# action is triggered if script returns non-nil value SecRuleScript "/etc/modsecurity/data/rewards-request_03-5.lua" \ "phase:2,t:none,log,auditlog,deny,severity:3,msg:'Luascript: \ AJAX Security -> 3.5 XML Injection: request is pending', \ tag:'INJECTION_ATTACK',redirect:/_error_pages_/lesson03-5.html" SecAction "phase:2,allow:request,t:none,log,auditlog,msg:'Luascript: \ AJAX Security -> 3.5 XML Injection: no illegal attempts made to add rewards'"

Refer to the Lua script 'rewards-request_03-5.lua'. The steps are:
 * get the POST request parameters
 * loop through them and for each 'check*' argument name, increment the number of rewards by 1
 * count the number of rewards in the data file
 * compare the total and return an error if not equal

Comments

 * This lesson shows how to use a 'do' loop in Lua and retrieve POST parameter names and values