The SpiderLabs Research Team has added an example script to the OWASP ModSecurity Core Rule Set (CRS) Project archive that will help users to quickly implement virtual patches for vulnerabilities identified by an open source web vulnerability scanning tool. The example script (zap2modsec.pl) is located in the /util directory of the CRS archive in SVN and will auto-convert XML data from the OWASP Zed Attack Proxy (ZAP) vulnerabiltiy scannint tool into custom ModSecurity rules.
Thanks goes out to Psiinon for fixing who fixed the ticket I created which adds in the vulnerable parameter name to the XML report data.
While this example script can only currently process ZAP XML report data, the script could be adapted to process other DAST tools by updating the XML::Smart variables to handle different schemas. The script will parse the XML data from ZAP reports and will auto-create ModSecurity rules for the following attack/vulnerability categories:
Here is an example SQL Injection vulnerablity in the Acunetix AcuForum ASP Site as found by ZAP:
Here is how ZAP reports it:
If we export the report data to XML format, here is how this vulnerabilitly looks:
<alertitem>
<pluginid>40005</pluginid>
<alert>SQL Injection</alert>
<riskcode>3</riskcode>
<reliability>1</reliability>
<riskdesc>High (Suspicious)</riskdesc>
<desc>SQL injection is possible. User parameters submitted will be formulated into a SQL query for database processing. If the query is built by simple 'string concatenation', it is possible to modify the meaning of the query by carefully crafting the parameters. Depending on the access right and type of database used, tampered query can be used to retrieve sensitive information from the database or execute arbitrary code. MS SQL and PostGreSQL, which supports multiple statements, may be exploited if the database access right is more powerful.
This can occur in URL query strings, POST paramters or even cookies. Currently check on cookie is not supported by Paros. You should check SQL injection manually as well as some blind SQL injection areas cannot be discovered by this check.
</desc>
<uri>http://testasp.vulnweb.com/Search.asp?tfSearch='INJECTED_PARAM</uri>
<param>tfSearch</param>
<attack>'INJECTED_PARAM</attack>
<otherinfo>SQL</otherinfo>
<solution>Do not trust client side input even if there is client side validation. In general, If the input string is numeric, type check it.
If the application used JDBC, use PreparedStatement or CallableStatement with parameters passed by '?'
If the application used ASP, use ADO Command Objects with strong type checking and parameterized query.
If stored procedure or bind variables can be used, use it for parameter passing into query. Do not just concatenate string into query in the stored procedure!
Do not create dynamic SQL query by simple string concatentation.
Use minimum database user privilege for the application. This does not eliminate SQL injection but minimize its damage. Eg if the application require reading one table only, grant such access to the application. Avoid using 'sa' or 'db-owner'.
</solution>
<otherinfo>SQL
</otherinfo>
<reference>The OWASP guide at http://www.owasp.org/documentation/guide
http://www.sqlsecurity.com/DesktopDefault.aspx?tabid=23
http://www.spidynamics.com/whitepapers/WhitepaperSQLInjection.pdf
For Oracle database, refer to http://www.integrigy.com/info/IntegrigyIntrotoSQLInjectionAttacks.pdf
</reference>
</alertitem>
The XML data highlighted can be parsed by the scripts to create a ModSecurity rule based on the injection point (URL + Parameter name) and vulnerability category.
The true value of levaraging vulnerability scanner data is confirmation of a known attack vector location or injection point for a specific attack category (such as SQL Injection). Now that you know where a vulnerability exists, the question is how do you want to protect against it? Ideally, you should use a positive security model which will only allow the data types and lengths that you want. If that is not possible, then you can use a negative security approach and deny things that you consider bad. In the case of using DAST data, it becomes tricky if you want to use attack payloads used during the test. The reason is that oftentimes the payloads used during testing are inference-based and geared towards identify a vulnerability vs. actual malicious payloads used by attackers. Vulnerability scanning is used to identify if a vulnerability exists, not to identify all of the possible exploitation variations.
So how can we identify attacks attempting to exploit these vulnerable resources?
The ModSecurity Core Rule Set uses the concept of "generic attack payload detection" where it has many different methods of identifying malicious payloads where ever they may exist. It does not, however, know if this is a known vulnerable injection point. The result is that there is a higher degree of false positives. When we uuse both the CRS generic detection along with the known attack injection point intelligence from the vulnerability scanner XML output, the user can have an increased confidence in blocking. Running the Virtual Patching Scripts To run the scripts, simply specify which XML file to use as input:
$ ./zap2modsec.pl
Flag:
-f: path to ZAP xml report file
Usage:
./zap2modsec.pl -f ./zap_report.xml
$ ./zap2modsec.pl -f ./zap-acuforum.xml
==================================================================================================
Vulnerability[10] - Type: SQL Injection Fingerprinting
Found a SQL Injection Fingerprinting vulnerability.
Validating URL: http://testasp.vulnweb.com/Search.asp?tfSearch='INJECTED_PARAM
URL is well-formed
Continuing Rule Generation
Current vulnerable Param(s): tfSearch
==================================================================================================
Vulnerability[11] - Type: SQL Injection
Found a SQL Injection vulnerability.
Validating URL: http://testasp.vulnweb.com/Search.asp?tfSearch='INJECTED_PARAM
URL is well-formed
Continuing Rule Generation
Current vulnerable Param(s): tfSearch
SQL Injection (uricontent and param) rule successfully generated and saved in ./modsecurity_crs_48_virtual_patches.conf.
==================================================================================================
Vulnerability[12] - Type: Cross Site Scripting
Found a Cross Site Scripting vulnerability.
Validating URL: http://testasp.vulnweb.com/Search.asp?tfSearch=javascript:alert(1);
URL is well-formed
Continuing Rule Generation
Current vulnerable Param(s): tfSearch
Cross Site Scripting (uricontent and param) rule successfully generated and saved in ./modsecurity_crs_48_virtual_patches.conf.
==================================================================================================
************ END OF SCRIPT RESULTS *****************
Number of Vulnerabilities Processed: 17
Number of ModSecurity rules generated: 2
Number of Unsupported vulns skipped: 14
Number of bad URLs (rules not gen): 0
****************************************************
----------------------------------------------------
To activate the virtual patching file (./modsecurity_crs_48_virtual_patches.conf),
copy it into the CRS "base_rules" directory and then create
a symlink to it in the "activated_rules" directory.
-----------------------------------------------------
As you can see, there were both Cross-site Scripting and SQL Injection vulns found within the ZAP report. Let's now take a look at an example ModSecurity rule created based on the vuln data:
#
# OWASP ZAP Virtual Patch Details:
# ID: 111
# Type: SQL Injection
# Vulnerable URL: Search.asp
# Vulnerable Parameter: tfSearch
#
SecRule REQUEST_FILENAME "Search.asp" "chain,phase:2,t:none,block,msg:'Virtual Patch for SQL Injection',id:'111',tag:'WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',logdata:'%{matched_var_name}',severity:'2'"
SecRule &TX:'/SQL_INJECTION.*ARGS:tfSearch/' "@gt 0" "setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score}"
As you can see, the first SecRule is checking the request line data to make sure that it matches the vulnerable resource. We then run a 2nd chained rule that, instead of looking separately for the existence of the parameter name and a regex match, it simply inspects previously matched TX variable meta-data. In this case, if a previous CRS rules had already identified an SQL Injection attack payload in the "ARGS:tfSearcht" parameter location, then the rule matches.
If you would like to participate in a hands-on virtual patching workshop, you can sign up for the OWASP AppSecDC event. I will be leading this 2-day training session (April 2nd - 3rd, 2012) where we will not only discuss virtual patching theory but also have numerous hands-on labs where you can try to virtually patch many of the OWASP WebGoat vulnerabilties.