Archive for December, 1969

Webinar Featuring WHID on the Top Trends in Web Application Threats

Wednesday, December 31st, 1969

On April 11th I’m going to present a webinar on web application security, with a twist. The Webinar will outline the top threats to web sites in 2006 and will predict the trends of web attacks for 2007, but while most discussions of web site security vulnerabilities traditionally focused on the technical complexity of these attacks this time I will try to focus on the business impact of the vulnerabilities.

The traditional “techie” approach is to an extent based on “fear factor” and does not provide tools to assess the risk associated with web application vulnerabilities and therefore the effort and resources required to mitigate them.

This WebEx will use the Web Hacking Incident Database to prioritize web based attacks based on their actual business impact by examining past web site break-ins. The presentation will unveil a major upgrade to the Web Hacking Incident Database project, a Web Application Security Consortium project that documents known web site security incidents. The new upgrade will add business impact information to each incident in addition to the technical information available today.

The WebEx is targeted both at decision makers faced with the dilemma of budgeting web application security mitigation as well as consultants & security professionals tasked with performing risk assessment to web sites and web based applications.

Further details and registration at Breach Security Webinar Center

Regular Expression Development Tools

Wednesday, December 31st, 1969

Since ModSecurity is based on regular expressions, a lot of rule creation requires developing and testing regular expressions. Therefore I looked for a tool that can be used to test regular expressions for validity and accuracy before using the regular expression in a ModSecurity rule. I found two free tools that let you do that:

  • The Regex Coach is simple and powerful. You simply type your expression at the upper box and text to match at the bottom one and any matches, if found, are highlighted in the text. In between the boxes you can control the regular expression flags such as “ignore case” or “global match”. The Regex Coach does not stop there, it provides insight into the regular expression matching process but showing a tree view of the regular expression and letting you follow the matching process step by step.
  • Expresso - Unfortunately The Regex Coach chokes on the regular expressions we use in ModSecurity Core Rule Set. So I searched and found an alternative that works fine with our regular expression: Expresso. While free, it is not your typical open source software. Apart from using .NET framework, it politely asks for a (free) registration and generally seems to move away from free. It is also more complex and while very strong on peripheral features such as a library of regular expressions and saving your test work in a project file, it actually knows less about regular expressions. But it works with complex ones.

2.X/1.X Rule differences for identify missing/empty headers and variables

Wednesday, December 31st, 1969

There are certain scenarios where you might want to create white-listed ModSecurity rulesets which enforce that certain headers/variables are both present and not empty. This Blog entry highlights an important difference between the 1.X and 2.X ModSecurity Rules Languages in this regard.

ModSecurity 2.X Rules
There are some good examples of this in Core Rules file - modsecurity_crs_21_protocol_anomalies.conf file. Take for example the following entries -

SecRule &REQUEST_HEADERS:Host "@eq 0" "skip:1,log,auditlog,msg:'Request Missing a Host Header',id:'960008',severity:'4'"
SecRule REQUEST_HEADERS:Host "^$" "log,auditlog,msg:'Request Missing a Host Header',id:'960008',severity:'4'"

The 1st rule uses the "&" operator to enable counting the number of variables in a collection. So, this 1st rule will identify if the Host header is not present in the request. The 2nd rule uses the RegEx "^$" that will match if the Host header is present, but is empty.

ModSecurity 1.X Rules
The older ModSecurity 1.X rules language operated a bit differently. If you wanted to use a similar rule as the one above, you could use this rule -

SecFilterSelective HTTP_Host "^$"

This rule means two different things -
1) The Host header is missing and/or
2) The Host header is empty

Which is better?
On the surface, you might think "The 1.X rules way is better since you only need 1 rule..." however you need to realize that anytime you have rules or directives that implicitly enforce certain capabilities you run the risk of having false positives as it could match things that you didn't want them to. For instance, what if you have a situation where certain web clients (such as mobile devices) legitimately include some headers, however they are empty? Do you want to automatically block these clients? With the ModSecurity 1.X Rule Language, you would have to remove the entire rule. With the ModSecurity 2.X Rule Language, however, you are able to create rules to more accurately apply the logic that you desire.

ModSecurity Console: Purpose and Deployment

Wednesday, December 31st, 1969

If you have more then 1 ModSecurity installation, you have undoubtedly run into issues with consolidating, analyzing and responding to alert messages. Yes, you can always reconfigure Apache to send its access/error logs through Syslog onto a remote, central logging server however the data being forwarded is a very small subset of the entire transaction. It is only a warning message and not enough information to conduct proper incident response to determine if there was a false positive or if it was a legitimate attack. In order to determine this information, you need access to the ModSecurity Audit log files. Unfortunately, the original "Serial" format of the audit log was multi-line with all records held within one file. This made remote logging difficult. What was really needed was to have a mechanism to send logs onto a centralized logging host made specifically for processing ModSecurity Alert data. This is the purpose of the ModSecurity Console.

Although you can deploy the ModSecurity Console on the same host that is running ModSecurity, the recommended solution is to deploy the Console on a stand-alone server and then reconfigure your various ModSecurity hosts to send their logs across the network to the Console. This provides two benefits:

1) Management of the audit logs is centralized and thus makes analysis easier, and
2) If the web server were to be compromised, the audit logs would not be held locally where an attacker could delete them.

DEPLOYMENT
There are essentially 3 components that need to be configured and working correctly for this deployment to work:

1) The Console itself must be up and running and have profiles setup for each Sensor.
2) The ModSecurity configuration files on the individual installations must have the proper Audit logging directives configured, and
3) The modsec-auditlog-collector.pl script must be configured with the correct information.

The following steps will show you how to set these all up.

STEP 1: Install the Console software on the central log host
Follow the installation steps outlined in the README.txt file that comes with the software. Once you have installed the ModSecurity Console software on your logging host, you should then log into the web interface. Let's say that the Console host has an IP address of - 192.168.1.100. You should then login by going to - http://192.168.1.100:8886/. You will then get a Basic Auth login popup box. Login with "admin" as username and "admin" as password.

STEP 2: Create sensor profiles
You need to create Sensor profiles on the ModSecurity console. The term Sensor simply means a remote installation of ModSecurity. The Sensor profile is created to uniquely identify the incoming audit logs from each other and to optionally implement password/IP access controls. Click on the "Sensors" link at the top of the Console page and then click on the "Add Sensor" button. Next, fill in the appropriately Sensor Details such as Sensor Name, IP Address, Sensor Password and then click on Submit. You need to remember this information when you are editing the modsec-auditlog-collector.pl script on each Sensor host. Let's say for this sensor, the IP Address is 192.168.1.101, Username is alpha1 and the Password is sensor1.

STEP 3: Reconfigure the Audit Directives on each Sensor to use Concurrent Logging
The next step is to update a few of the audit directives in the configuration file of the individual ModSecurity installs.

Edit these directives so they look like this -

SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4\d[^4])"
SecAuditLogType Concurrent
SecAuditLogParts ABCDEFGHZ
SecAuditLogStorageDir /path/to/apache/logs/data/
SecAuditLog /path/to/apache/logs/audit.log

STEP 4: Test local concurrent logging
Once this is configured, you should restart Apache, send a few requests that will trigger a ModSecurity rule and then check the SecAuditLog file for the new, concurrent data. The format should look something similar to this -

192.168.2.101 192.168.2.11 - - [15/Jul/2005:11:56:52 +0100] "POST /form.php HTTP/1.1" 403
3 "http://192.168.2.101:8080/form.php" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) 
Gecko/20050511 Firefox/1.0.4" G3yTd38AAAEAAAM7BLwAAAAA "-" /20050715/20050715-1156/20050715-
115652-G3yTd38AAAEAAAM7BLwAAAAA 0 1031 md5:dc910f6d647d47b32ae6e47326f0ca42

The bolded section of the log entry is the location of the individual audit log file under the SecAuditLogStorageDir location. If you then looked at the following location - /path/to/apache/logs/data/20050715/20050715-1156/20050715-
115652-G3yTd38AAAEAAAM7BLwAAAAA - you would find the entire audit log record. Once you have confirmed that Concurrent logging is working correctly in local mode, the next step is to setup the modsec-auditlog-collector script with the correct information.

STEP 5: Update the modsec-auditlog-collector.pl script
You can download the modsec-auditlog-collector.pl code from within the web interface of the ModSecurity Console. Once you are logged in, click on the "About" link and then use "this Perl script" link. Once you download the script, you should upload it to your ModSecurity host and place it in the /path/to/apache/bin/ directory. You then need to do the following:

1) Chmod the script to make sure that it is executable by Root.
2) Verify that the path to Perl is correct in the script.
3) Edit the following lines within the script -

my $CONSOLE_URI = "/rpc/auditLogReceiver";
my $CONSOLE_HOST = "192.168.1.100";
my $CONSOLE_PORT = "8886";
my $CONSOLE_USERNAME = "alpha1";
my $CONSOLE_PASSWORD = "sensor1";

It is important that you specify the correct IP address for your ModSecurity Console host and that you also specify the correct Sensor Username and Password that you created within the ModSecurity Console. If any of this information is not correct, the modsec-auditlog-collector.pl script will not successfully tranfer the audit log files. After updating the modsec-auditlog-collector.pl script, the next step is to update one of the ModSecurity audit directives again.

STEP 6: Update the SecAuditLog Directive
Edit the ModSecurity configuration file once again and edit the SecAuditLog directive like this -

SecAuditLog "|/path/to/apache/bin/modsec-auditlog-collector.pl \
/path/to/apache/logs/data/ /path/to/apache/logs/audit.log"

What this is doing is using the "|" piped log feature to send the audit log data directly to the modsec-auditlog-collector.pl script. It also has two arguments, the first one being the path to the directory location specified by SecAuditLogStorageDir and the original SecAuditLog file that holds the audit log meta-data. Once you have updated this this directive, you should then restart Apache.

STEP 7: Testing Remote Logging
The final step is to verify that the remote ModSecurity Sensor will now send its Concurrent audit log data to the central Console. In order to do this, you should send another request to the ModSecurity Sensor that will trigger one of the Core Rules. This will then result in an audit log being created, passed to the modsec-auditlog-collector.pl script and then sent across the network to the Console.

In the Console, you should see the remote audit log file show up under the "Alerts" page in the Console. You can then click on the alert file link for all of the details.

Conclusion
Hopefully, this information will assist ModSecurity users with deploying their ModSecurity Consoles.

Top 10 Web Hacks of 2006

Wednesday, December 31st, 1969

Jeremiah Grossman gives an excellent overview of the top Web hacks of 2006. If you haven"t been following the events as they unfolded last year this presentation alone will help you catch up.

Weekly SANS @RISK Web Vulnerabilities List & Mitigation Steps

Wednesday, December 31st, 1969

This is a listing of Web Application Vulnerabilities that were released by SANS in their @RISK newsletter yesterday -

--------------
Summary of the vulnerabilities reported this week:
--------------
-- Web Application - Cross Site Scripting (8)
07.5.44 - ezDatabase Login.PHP Cross-Site Scripting
07.5.45 - Openads phpAdsNew Admin-Search.PHP Cross-Site Scripting
07.5.46 - 212cafeBoard Multiple Cross-Site Scripting Vulnerabilities
07.5.47 - Bitweaver Articles and Blogs Multiple Cross-Site Scripting Vulnerabilities
07.5.48 - 212Cafe Guestbook Show.PHP Cross-Site Scripting
07.5.49 - Openads for PostgreSQL Unspecified Cross-Site Scripting
07.5.50 - PostNuke Reviews Index.PHP Cross-Site Scripting
07.5.51 - Sabros.US Index.PHP Cross-Site Scripting

-- Web Application - SQL Injection (10)
07.5.52 - Makit Newsposter Script News_Page.ASP SQL Injection
07.5.53 - GPS CMS Print.ASP SQL Injection
07.5.54 - ASP News News_Detail.ASP SQL Injection
07.5.55 - ASP Edge User.ASP SQL Injection
07.5.56 - Drupal Acidfree Module Node Title SQL Injection
07.5.57 - Website Baker Login.PHP SQL Injection
07.5.58 - FishCart Olst Parameter SQL Injection
07.5.59 - Unique Ads Banner.PHP SQL Injection
07.5.60 - PHP-Nuke Multiple SQL Injection Vulnerabilities
07.5.61 - Joomla CMS Multiple SQL Injection Vulnerabilities

-- Web Application (34)
07.5.62 - CGI Rescue WebForm Multiple Input Validation Vulnerabilities
07.5.63 - High5 Review Script Search Field HTML Injection
07.5.64 - Virtual Path PHPBB Module Configure.PHP Remote File Include
07.5.65 - Digitalxero Xero Portal PHPBB_Root_Path Multiple Remote File Include Vulnerabilities
07.5.66 - Drupal Project and Project Issues Tracking Modules Multiple Vulnerabilities
07.5.67 - Community Server Pingback SourceURI Denial of Service and Information Disclosure
07.5.68 - AWFFull Unspecified Multiple Buffer Overflow Vulnerabilities
07.5.69 - Virtual Host Administrator Modules_Dir Remote File Include
07.5.70 - Wordpress Pingback SourceURI Denial of Service and Information Disclosure
07.5.71 - RPW Config.PHP Remote File Include
07.5.72 - phpXD Path Remote File Include
07.5.73 - MyBB Private.PHP HTML Injection
07.5.74 - MaklerPlus Multiple Unspecified Vulnerabilities
07.5.75 - Mini Web Server Unspecified Multiple Buffer Overflow Vulnerabilities
07.5.76 - BBClone Selectlang.PHP Remote File Include
07.5.77 - Yana Framework Guestbook Unspecified Security Bypass
07.5.78 - Vote! Pro Multiple PHP Code Execution Vulnerabilities
07.5.79 - PHP Link Directory Link Submission HTML Injection
07.5.80 - Zomp Index.PHP Local File Include
07.5.81 - PHPIndexPage Config.PHP Remote File Include
07.5.82 - Neon Labs Website NL.PHP Remote File Include
07.5.83 - XMB MemCP.PHP HTML Injection
07.5.84 - PHPSherpa Racine Parameter Remote File Include
07.5.85 - Upload Service Remote File Include
07.5.86 - Mafia Scum Tools Index.PHP Remote File Include
07.5.87 - WebChat Remote File Include
07.5.88 - Bradabra Includes.PHP Remote File Include
07.5.89 - Easebay Resources Paypal Subscription Manager Multiple Input Validation Vulnerabilities
07.5.90 - Easebay Resources Login Manager Multiple Input Validation Vulnerabilities
07.5.91 - SMF Index.PHP HTML Injection
07.5.92 - DocMan Multiple Input Validation Vulnerabilities
07.5.93 - ArsDigita Community System Directory Traversal
07.5.94 - VirtueMart Joomla ECommerce Edition Multiple Unspecified Input Validation Vulnerabilities
07.5.95 - WebGUI Registration Username HTML Injection

--------------
Mitigation Steps:
--------------
It is important to note that if you are running any of these web applications, you should do the following:

1) Check on the reference links for each vulnerability (SecurityFocus site, etc...) and verify if a patch is available. If one is, then proceed with implementing the patch ASAP.

2) Run a few tests to see if the example expoit code might be already captured by the current ModSecurity Core Rules files. There are already many different XSS/SQL Injection rules that probably would block the vast majority of these 2 categories of issues. If the Core Rules do not block these issues, then proceed to #3 (Virtual Patching).

3) Whether a patch is available or not, you should attempt to implement a ModSecurity "Virtual Patch" for the vulnerability. You can go about this in one of two ways -

First, the vulnerability information on SecurityFocus usually include an "exploit" tab for each vulnerability where exploit details/proof of concept code is often provided. You can take the example exploit code and then create a corresponding patch. The patch can either be a negative filter that blocks the underlying vulnerability vector. You can also, optionally, create a positive filter that will only allow acceptable character sets/lengths, etc...

Second, you can optionally head on over to the Snort.org site to see if they have released an IDS signatures for these vulnerabilities. If they have, you can then take the content/uricontent/pcre portions of the sigs and translate them into analagous ModSecurity rules.

ModSecurity 2.1.0 Improvements

Wednesday, December 31st, 1969

I have just packaged and released ModSecurity for Apache v2.1.0-rc7, in preparation for the first stable release in the 2.1.x branch. I am very fond of having many release candidates over a period of time. They have an important role of demonstrating how the process of adding new features has ended, and the product is now being polished for a release.

A lot of work has been done in the v2.1.0, with quality being the main focus. Ryan Barnett - a well known member of the ModSecurity community and an employee of Breach Security since last year (and thus a member of the ModSecurity project) - contributed by creating a set of regression tests and updating the documentation. Ofer (whom you already know by know as the person in charge of the Core Rules project) helped by thoroughly testing both ModSecurity and Core Rules, all as part of our parallel effort - the ModSecurity appliance - ModSecurity Pro M1000. Their combined efforts have resulted in a discovery of a number of small issues that were promptly fixed.

But even if you are not affected by some of the problems that were now fixed in v2.1.0 there are good reasons to upgrade - this new version is almost twice as fast for real-life traffic and uses significantly less memory.

We will officially declare v2.1.0 stable in a week or so but I urge you to take the release candidate for a spin to make sure it works for you. It's time to move on and start implementing the next batch of changes. We have some very interesting features on our TODO list!

PHP Peculiarities for ModSecurity Users

Wednesday, December 31st, 1969

As I was reviewing the ModSecurity 2.1.0-rc7 Reference Manual I realised it did not contain some very important sections we had in the previous (ModSecurity 1.9.x) manual - those on web application firewall impedance mismatch and PHP peculiarities. Impedance mismatch is a well known problem where, because web application firewalls interpret input data independently from the systems they are protecting, there is a danger of information slipping through because of different interpretations. PHP is especially vulnerable to this issue because the engine was designed to be error friendly and "helpful".

For many years now my policy was to try to document the evasion possibilities and to lay the responsibility on the ModSecurity user to read the manual. I have now decided to make the issue more visible. To start with, here's the part from the 1.9.x manual that is relevant to PHP:

  1. When "register_globals" is set to "On" request parameters are automatically converted to script variables. In some PHP versions it is even possible to override the $GLOBALS array.

  2. Whitespace at the beginning of parameter names is ignored. (This is very dangerous if you are writing rules to target specific named variables.)

  3. The remaining whitespace (in parameter names) is converted to underscores. The same applies to dots and to a "[" if the variable name does not contain a matching closing bracket. (Meaning that if you want to exploit a script through a variable that contains an underscore in the name you can send a parameter with a whitespace or a dot instead.)

  4. Cookies can be treated as request parameters.

  5. The discussion about variable names applies equally to the cookie names.

  6. The order in which parameters are taken from the request and the environment is EGPCS (environment, GET, POST, Cookies, built-in variables). This means that a POST parameter will overwrite the parameters transported on the request line (in QUERY_STRING).

  7. When "magic_quotes_gpc" is set to "On" PHP will use backslash to escape the following characters: single quote, double quote, backslash, and the null byte.

  8. If "magic_quotes_sybase" is set to "On" only the single quote will be escaped using another single quote. In this case the "magic_quotes_gpc" setting becomes irrelevant. The "magic_quotes_sybase" setting completely overrides the "magic_quotes_gpc" behaviour but "magic_quotes_gpc" still must be set to "On" for the Sybase-specific quoting to be work.

  9. PHP will also automatically create nested arrays for you. For example "p[x][y]=1" results in a total of three variables.

(Update Feb 7) Jakub Vrána wrote to clarify that "magic_quotes_gpc" must be "On" for "magic_quotes_sybase" to work. Thanks! This is now fixed. Jakub has a post in Czech on a similar topic.

Httprint vs. ModSecurity

Wednesday, December 31st, 1969

There was a great email posted to the ModSecurity user mail-list today that asked about ModSecurity's ability (or inability) to trick web server fingerprinting tools such as HTTPrint. The short answer is YES, ModSecurity 2.X can be used to effectively ruin the accuracy of HTTPrint. The most important point here is that ModSecurity 2.X now has a hook in to the Apache PostReadRequest portion of the request cycle (phase:1) where previously it would run much later in the Fixup phase (phase:2). In order understand how HTTPrint works, I suggest that you read this supporting information.

There are many different possibilities for mitigating the effectiveness of these types of fingerprinting scanners. For complete information, I suggest you read the http fingerprinting Appendix section I wrote as part of the WASC Threat Classification document.

HTTPrint a not a typical "banner grabbing" application, as it has more logic to it. It's main fingerprinting technique has to do with the Sematic differences in how web servers/applications respond to various stimuli. Let's take a look.

If I run HTTPrint v0.301 (the most recent version) against a default Apache 2.2.3 web server, it reports the following:

$ ./httprint -h 192.168.10.27 -s signatures.txt
httprint v0.301 (beta) - web server fingerprinting tool
(c) 2003-2005 net-square solutions pvt. ltd. - see readme.txt
http://net-square.com/httprint/
httprint@net-square.com

Finger Printing on http://192.168.10.27:80/
Finger Printing Completed on http://192.168.10.27:80/
--------------------------------------------------
Host: 192.168.10.27
Derived Signature:
Apache/2.2.0 (Fedora)
9E431BC86ED3C295811C9DC5811C9DC5050C5D32505FCFE84276E4BB811C9DC5
0D7645B5811C9DC5811C9DC5CD37187C11DDC7D7811C9DC5811C9DC58A91CF57
FCCC535B6ED3C295FCCC535B811C9DC5E2CE6927050C5D336ED3C2959E431BC8
6ED3C295E2CE69262A200B4C6ED3C2956ED3C2956ED3C2956ED3C295E2CE6923
E2CE69236ED3C295811C9DC5E2CE6927E2CE6923

Banner Reported: Apache/2.2.0 (Fedora)
Banner Deduced: Apache/2.0.x
Score: 140
Confidence: 84.34
------------------------
Scores:
Apache/2.0.x: 140 84.34
Apache/1.3.[4-24]: 132 68.91
Apache/1.3.27: 131 67.12
Apache/1.3.26: 130 65.36
Apache/1.3.[1-3]: 127 60.28
--CUT--

As you can see, it correctly fingerprinted my Server as an Apache 2.X server. The only reason that it wasn't any more accurate was that it didn't have a signature for 2.2.3 yet (but that is easily fixed by pasting the fingerprint above into the signatures.txt file with the proper label). Anyways, after running this scan, my Apache logs show this info:

192.168.10.69 - - [15/Jan/2007:12:26:20 -0500] "\x16\x03" 501 214
192.168.10.69 - - [15/Jan/2007:12:26:20 -0500] "GET / HTTP/1.0" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / HTTP/1.0" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "OPTIONS * HTTP/1.0" 200 -
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "OPTIONS / HTTP/1.0" 200 -
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET /antidisestablishmentarianism HTTP/1.0" 404 226
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "PUT / HTTP/1.0" 405 231
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "JUNKMETHOD / HTTP/1.0" 501 222
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / JUNK/1.0" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "get / http/1.0" 501 215
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "POST / HTTP/1.0" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET /cgi-bin/ HTTP/1.0" 403 210
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET /scripts/ HTTP/1.0" 404 206
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / HTTP/0.8" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / HTTP/0.9" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / HTTP/1.1" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / HTTP/1.2" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / HTTP/1.1" 400 226
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / HTTP/1.2" 400 226
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET / HTTP/3.0" 200 44
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET /.asmx HTTP/1.1" 404 203
192.168.10.69 - - [15/Jan/2007:12:26:21 -0500] "GET /../../ HTTP/1.0" 400 226

What is important to notice are the various HTTP Response Codes that Apache trigger based on the different malformed requests. There were 501s, 400s and some 200s.

Now, if we want to use ModSecurity to combat HTTPrint, we need to use signatures that enforce HTTP Compliance as this is the core of HTTPrint's Semantic tests. Fortunately, the ModSecurity Core Rules come with many different rules that will help to enforce HTTP compliance. After impelmenting ModSecurity + the Core Rules, if I re-run HTTPrint you will see that it isn't even able to complete it's tests and it errors out:

$ ./httprint -h 192.168.10.27 -s signatures.txt
httprint v0.301 (beta) - web server fingerprinting tool
(c) 2003-2005 net-square solutions pvt. ltd. - see readme.txt
http://net-square.com/httprint/
httprint@net-square.com

Finger Printing on http://192.168.10.27:80/
Finger Printing Completed on http://192.168.10.27:80/
--------------------------------------------------
Host: 192.168.10.27
Fingerprinting Error: Invalid response from server, check configuration...
--------------------------------------------------

Now, back in the Apache access log file you will see that HTTPrint actually sent only 2 requests and ModSecurity responded with status codes of 400 for both:

# cat access_log
192.168.10.69 - - [15/Jan/2007:12:57:27 -0500] "\x16\x03" 400 226
192.168.10.69 - - [15/Jan/2007:12:57:27 -0500] "GET / HTTP/1.0" 400 226

The error_log shows why ModSecurity blocked the requests:

[Mon Jan 15 12:57:27 2007] [error] [client 192.168.10.69] ModSecurity: Access denied with code 400 (phase 1). Operator EQ match: 0. [id "960008"] [msg "Request Missing a Host Header"] [severity "WARNING"] [uri ""] [unique_id "@om-EcCoChsAABmtbhgAAAAA"]
[Mon Jan 15 12:57:27 2007] [error] [client 192.168.10.69] ModSecurity: Access denied with code 400 (phase 1). Operator EQ match: 0. [id "960015"] [msg "Request Missing an Accept Header"] [hostname "192.168.10.27"] [uri "/"] [unique_id "@onadMCoChsAABmubtAAAAAB"]

As you can see, HTTPrint did not send certain mandatory requests headers (host and accept) so ModSecurity blocked the requests. Now, due to the fact that these first few requests sent by HTTPrint are supposed to be used to baseline normal response, the status codes of 400 were not expected and it therefore errored out.

Even if I remove these 2 Core Rules signatures, there are other rules that would still trigger block the requests. These include the check for a User-Agent request header, verifying that the Host header is an actual name and not an IP address (as that is normally indicative of worm activity, there are also other signatures that can enforce only the GET|HEAD|POST request methods and ensure that the request ends in HTTP and one of the legitimate protocol numbers (0.9, 1.0 or 1.1). With this layered approach, ModSecurity can provide effective defenses against the HTTPrint scanner.

Testing Core Rules Protection For An Example SQL Injection Vulnerability

Wednesday, December 31st, 1969

SANS released their 6th edition of the @RISK Weekly News Letter. In it, there were a total of 44 new web application vulnerabilities identified. Keep in mind that almost all of these vulnerabilities (I didn't get a chance to verify each and everyone of them) can be mitigated with the use of the Core Rules. For example, take this specific vulnerability:

07.6.37 CVE: Not Available
Platform: Web Application - SQL Injection
Title: ExoPHPDesk FAQ.PHP SQL Injection
Description: ExoPHPDesk is a web-based help desk application. It is
prone to an SQL injection issue because it fails to sufficiently
sanitize user-supplied data to the "id" parameter of the "faq.php"
script before using it in an SQL query. ExoPHPDesk versions 1.2.1 and
earlier are affected.
Ref: http://www.securityfocus.com/bid/22338

If you go to the SecurityFocus page and click on the "exploit" link you will see this example URL attack:

http://www.example.com/faq.php?action=&type=view&s=&id=-1'%20union%20select%200,concat(char(85),char(115),
char(101),char(114),char(110),char(97),char(109),char(101),char(58),name,char(32),char(124),char(124),char(32),
char(80),char(97),char(115),char(115),char(119),char(111),char(114),char(100),char(58)
,pass),0,0,0,0,0%20from%20phpdesk_admin/*

If you were to send this request to a host that is protected by ModSecurity + the most recent release of the Core Rules, it would be identified by the following rule -

# SQL injection
SecRule REQUEST_FILENAME|ARGS|ARGS_NAMES|REQUEST_HEADERS|!REQUEST_HEADERS:Referer "(?:\b(?:(?:s(?:elect\b(?:.{1,100}?
\b(?:(?:length|count|top)\b.{1,100}?\bfrom|from\b.{1,100}?\bwhere)|.*?\b(?:d(?:ump\b.*\bfrom|ata_type)|(?:to_(?:numbe
|cha)|inst)r))|p_(?:(?:addextendedpro|sqlexe)c|(?:oacreat|prepar)e|execute(?:sql)?|makewebtask)|ql_(?:longvarchar|var
iant))|xp_(?:reg(?:re(?:movemultistring|ad)|delete(?:value|key)|enum(?:value|key)s|addmultistring|write)|e(?:xecresul
tset|numdsn)|(?:terminat|dirtre)e|availablemedia|loginconfig|cmdshell|filelist|makecab|ntsec)|u(?:nion\b.{1,100}?\bse
lect|tl_(?:file|http))|group\b.*\bby\b.{1,100}?\bhaving|load\b\W*?\bdata\b.*\binfile|(?:n?varcha|tbcreato)r|autonomou
s_transaction|open(?:rowset|query)|dbms_java)\b|i(?:n(?:to\b\W*?\b(?:dump|out)file|sert\b\W*?\binto|ner\b\W*?\bjoin)\
b|(?:f(?:\b\W*?\(\W*?\bbenchmark|null\b)|snull\b)\W*?\()|(?:having|or|and)\b\s+?(?:\d{1,10}|'[^=]{1,10}')\s*?[=<>]+|(
?:print\]\b\W*?\@|root)\@|c(?:ast\b\W*?\(|oalesce\b))|(?:;\W*?\b(?:shutdown|drop)|\@\@version)\b|'(?:s(?:qloledb|a)|m
sdasql|dbo)')" \
"capture,t:replaceComments,ctl:auditLogParts=+E,log,auditlog,
msg:'SQL Injection Attack. Matched signature <%{TX.0}>',id:'950001',severity:'2'"

The resulting alert message would look like this:

[Wed Jan 17 11:01:16 2007] [error] [client 192.168.10.10] ModSecurity: Warning. Pattern match
"(?:\\\\b(?:(?:s(?:elect\\\\b(?:.{1,100}?\\\\b(?:(?:length|count|top)\\\\b.{1,100}?\\\\bfrom|
from\\\\b.{1,100}?\\\\bwhere)|.*?\\\\b(?:d(?:ump\\\\b.*\\\\bfrom|ata_type)|(?:to_(?:numbe|cha)|
inst)r))|p_(?:(?:addextendedpro|sqlexe)c|(?:oacreat|prepar)e|execute(?:sql)?|makewebt ..." at
ARGS:id. [id "950001"] [msg "SQL Injection Attack. Matched signature <union select>"] [severity "CRITICAL"]
[hostname "www.example.com"] [uri "/faq.php?action=&type=view&s=&id=-1'%20union%20select%200,concat(char(85),
char(115),char(101),
char(114),char(110),char(97),char(109),char(101),char(58),name,char(32),char(124),char(124),
char(32),char(80),char(97),char(115),char(115),char(119),char(111),char(114),char(100),char(58)
,pass),0,0,0,0,0%20from%20phpdesk_admin/*"] [unique_id "lqn99sCoChsAAHpfWokAAAAA"]

One very important note here:
By default, this SQL Injection rule is inheriting the following SecDefaultAction directive in the modsecurity_crs_40_general_attacks.conf file -

SecDefaultAction "log,pass,phase:2,status:500,t:urlDecodeUni,t:htmlEntityDecode,t:lowercase"

This means that while it did identify the attack, it did not block it. Your best course of action when implementing Core Rules is to run it with - SecRuleEngine DetectionOnly - until you have verified that there are no false positives in your environment. Afterwhich, you should change the SecDefaultAction settings within the rules files to actually use the "deny" action in order to prevent the attacks.

It is a good idea to periodically test out these types of exploit requests to ensure that your ModSecurity installation is functioning properly.