Thursday, March 03, 2016

Web Application Firewall in Ubuntu with Apache and ModSecurity

Here is a recipe to install and configure ModSecurity (mod_security) tested in Ubuntu 14.04 Apache.

Note that besides copying setup files we edit inline modsecurity.conf to make sure SecRuleEngine is set to On instead of DetectionOnly (switch between them to activate the rules or just get logging information) and to make sure SecAuditLogRelevantStatus is set to "^$" instead of "^(?:5|4(?!04))" (switch between them to get log entries when the application returns 4xx or 5xx status codes or not log them at all)

This recipe will activate sql and command injection protection rules. There are several other core rules you can add just by copying them to /etc/modsecurity and restarting the server after. There are base_rules, experimental_rules and optional_rules distributed in the ModSecurity project.

To test the effectiveness of sql injection protection do not activate the rule (remove the specific crs file from the /etc/modsecurity directory), restart the server and try the below request. Apache will pass it request to your application as usual
https://sample.com/foo?bar=%27%20or%20true%20--
Now activate the rule (put the specific crs file in the /etc/modsecurity directory), restart the server and try the same request. You receive a Forbidden status code (403). From logs (/var/log/modsec_audit.log) you can read:
Message: Access denied with code 403 (phase 2). Pattern match "(^[\"'`\xc2\xb4\xe2\x80\x99\xe2\x80\x98;]+|[\"'`\xc2\xb4\xe2\x80\x99\xe2\x80\x98;]+$)" at ARGS:a. [file "/etc/modsecurity/modsecurity_crs_41_sql_injection_attacks.conf"] [line "64"] [id "981318"] [rev "2"] [msg "SQL Injection Attack: Common Injection Testing Detected"] [data "Matched Data: ' found within ARGS:a: ' or true --"] [severity "CRITICAL"] [ver "OWASP_CRS/2.2.8"] [maturity "9"] [accuracy "8"] [tag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"] Action: Intercepted (phase 2)
The recipe also activates command injection which you can test as described above using the below url:
https://sample.com/foo?bar=curl
This is a fairly simple setup which I would consider basic to secure any production web application.

You might need to add exclusions for certain non compliant and existent URLs. Since developers could take take a while to fix several existent issues and you do not want to delay the Firewall protection here are some guidelines to smooth the installation and produce your MMF ASAP.

  • Set 'SecRuleEngine DetectionOnly' so that you can compile the current problems from the log file:
    sudo sed -i  's/^SecRuleEngine.*/SecRuleEngine DetectionOnly/' /etc/modsecurity/modsecurity.conf && sudo apachectl graceful
    
  • Find the modsecurity rule id for issues so far:
    cat /var/log/apache2/yourlogname.log|grep ModSecurity|grep -o 'id "[0-9]*"'|sort|uniq
    
  • Look into each error to look into URLs needing exceptions and what it is all about. For example for id 981240:
    cat /var/log/apache2/yourlogname.log | grep ModSecurity | grep 981240
    
    Also look into the definitive modsecurity log to confirm if in doubt:
    sudo less /var/log/modsec_audit.log 
    
  • Start adding your own rules. Note that I start at rule 1 as per the documentation and I put all of them in a custom.conf file:
    # Using 25 MB for upload limit
    SecResponseBodyLimit 26214400
    # Exceptions for URLs that violate PCRE limits, dangerous characters accepted and parameters too long
    SecRule REQUEST_URI "@contains /path/containing/service/accepting/long/parameters/content/and/literal/code/and/others "phase:1,t:none,pass,id:'1',nolog,ctl:ruleRemoveById=959070,ctl:ruleRemoveById=960024,ctl:ruleRemoveById=981173,ctl:ruleRemoveById=950901,ctl:ruleRemoveById=981231,ctl:ruleRemoveById=981240,ctl:ruleRemoveById=981243,ctl:ruleRemoveById=981245,ctl:ruleRemoveById=981318"
    
  • Sometimes you need to skip modecurity rules for a specific URI, for example:
    SecRule REQUEST_BASENAME "@contains blogs" "id:1,ctl:ruleEngine=Off"
    
  • Once you get no alerts in your integration environment where surely you constantly run automated e2e tests then you can set 'SecRuleEngine On' to enable the APP FW:
    sudo sed -i  's/^SecRuleEngine.*/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf &&  sudo apachectl graceful
    

No comments:

Followers