ONLamp.com    
 Published on ONLamp.com (http://www.onlamp.com/)
 See this if you're having trouble printing code examples


Securing Web Services with mod_security

by Shreeraj Shah
06/09/2005

Web services are increasingly becoming an integral part of next-generation web applications. They're also vulnerable to attacks. The nature of these attacks is the same as for traditional web applications, but the modus operandi is different. These attacks can lead to information leakage; further, they aid in remote command execution. By using WSDL, an attacker can determine an access point and available interfaces for web services. These interfaces or methods take inputs using SOAP over HTTP/HTTPS. Without good defense at the source code level, your application is in danger of compromise and exploitation. mod_security operates as an Apache web server module, ideal for defending web services against attacks that also include malicious POST data containing SOAP envelopes.

The Problem Domain

Web services have four main attack vectors:

Related Reading

Apache Security
By Ivan Ristic

Common firewall configurations allow incoming HTTP/HTTPS traffic to pass through unobstructed. Each of these attacks is, simply put, malicious incoming traffic camouflaged to look like legitimate HTTP/HTTPS traffic and therefore able to penetrate firewalls quite easily. This article examines ways and means to first distinguish between legitimate and malicious HTTP/HTTPS traffic, and then block such traffic. Doing so can mitigate port 80/443 attacks to a very great extent.

What Is the Solution?

Solutions can take many different forms, ranging from secure coding practices to proper input validation. One approach is to perform content validation for each incoming request and compare it with predefined rules. This approach stops malicious SOAP requests from penetrating to the web services source code level. mod_security can help in defending against all of the above attacks, if you have deployed and configured it properly for web services. This article discusses in detail how mod_security can be an effective web services defense tool.

After deploying web services, it is important to provide a sound defense against different sets of attack vectors. Each attack vector needs a different defense strategy. Consider a case study of a bank--a fictitious one and meant to serve only as an example.

Blue Bank (www.bluebank.example.com) has recently deployed web services securely using mod_security. It provides banking services over the internet for its financial partners and clients. Its web services provide online customer services such as account balances, money transfers, and modifying customer information. Figure 1 illustrates the web services deployment architecture at Blue Bank.

Blue Bank setup
Figure 1. Deployment at Blue Bank

There are many different ways to deploy web services. In this case, the web service runs on Tomcat/Axis and plugs into the Apache web server. The banking web services application is Java code (with the .jws file extension).

Relevant sample snippets of Apache and Axis configuration files include the Apache httpd.conf, which loads Tomcat:

LoadModule jk2_module modules/mod_jk2.so
JkSet config.file /usr/local/apache2/conf/workers2.properties

The Axis web.xml file, which supports AxisServlet for web services processing:

<servlet-mapping>                                            
    <servlet-name>AxisServlet</servlet-name>                 
    <url-pattern>*.jws</url-pattern>                         
</servlet-mapping>

Once the above configuration is in place, you can deploy any web services on this server. If you observe the header information sent out with this server's responses, you can identify this line:

Server: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4

The above header suggests that the web server is Apache/2.0.50 (Unix) running the Tomcat module mod_jk2/2.0.4. Axis runs as part of the Tomcat web application and is ready for the deployment of web services. To provide a defense at the web services level, Blue Bank has loaded the mod_security module that provides application-filtering capabilities. The following line in httpd.conf loads the security module:

LoadModule security_module    modules/mod_security.so

With mod_security in place, Blue Bank can add filtering rules in httpd.conf:

<IfModule mod_security.c> 
     # Turn the filtering engine On or Off
     SecFilterEngine On
     SecFilterDefaultAction "deny,log,status:500"
     SecFilterScanPOST On

     . . .
     # Other rules
     . . .
</IfModule>

With this, Blue Bank has everything in place for systems administrators and developers to build web services and use the mod_security's effective content filtering capability to defend against malicious incoming HTTP/HTTPS requests.

Consider a sample web service at www.bluebank.example.com/axis/getBalance.jws. The WSDL response for this specific web service comes from www.bluebank.example.com/axis/getBalance.jws?wsdl. Note: www.bluebank.example.com is a hypothetical domain used only as an example.

Method/Interface data derived from WSDL to show account balance

Scrutinize the WSDL response obtained as a result of the HTTP request passed. Of specific interest here is the invocation method, which takes the bank id and passes relevant account balance information back to the client over HTTP. The operation tag specifies methods that a web services client can invoke. The relevant snippets of the WSDL file include:

<wsdl:operation name="getInput">
 <wsdlsoap:operation soapAction=""/>
   <wsdl:input name="getInputRequest">
     <wsdlsoap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/
             namespace="http://DefaultNamespace"
             use="encoded"/>
   </wsdl:input>
   <wsdl:output name="getInputResponse">
     <wsdlsoap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/
             namespace="http://www.bluebank.example.com/axis/getBalance.jws"
             use="encoded"/>
   </wsdl:output>

<wsdl:message name="getInputResponse">
    <wsdl:part name="getInputReturn" type="xsd:string"/>
</wsdl:message>
<wsdl:message name="getInputRequest">
    <wsdl:part name="id" type="xsd:string"/>
</wsdl:message>

As shown above, passing an id to this particular method will cause it to return a string as output. When you pass a bank account id as input to the web service, you will receive the account balance available for that particular account id.

Invoking the web service over HTTP

Blue Bank's clients or partners seeking account balance information over the internet can fetch the requisite information by sending a properly formatted envelope to the banking web services. Figure 2 shows an HTTP request for account balance information for account id 12123 being sent to the web service.

Invoking Web Services
Figure 2. Invoking the web service over HTTP

There are several different ways to create SOAP clients that generate properly formatted SOAP requests. Here is an example of a SOAP client using SOAP::Lite in Perl. The following simple code generates a SOAP request on the wire.

#!perl -w
use SOAP::Lite;

print SOAP::Lite
  -> service('http://www.bluebank.example.com/axis/getBalance.jws?wsdl')
  -> getInput('12123');

It's also possible to sniff HTTP requests and responses on the wire using a sniffer such as ethereal. An HTTP/SOAP request sent to www.bluebank.example.com with the id of 12123 will generate something like:

POST /axis/getBalance.jws HTTP/1.0
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 576
Expect: 100-continue
Host: www.bluebank.example.com

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://www.bluebank.example.com/axis/getBalance.jws" xmlns:types="
http://www.bluebank.example.com/axis/getBalance.jws/encodedTypes"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
                <q1:getInput xmlns:q1="http://DefaultNamespace">
                        <id xsi:type="xsd:string">12123</id>
                </q1:getInput>
        </soap:Body>
</soap:Envelope> 

...

HTTP/1.1 200 OK
Date: Mon, 03 Jan 2005 19:24:10 GMT
Server: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4
Set-Cookie: JSESSIONID=69C6540CC427A8B064C0795ADDFC20EA; Path=/axis
Content-Type: text/xml;charset=utf-8
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <soapenv:Body>
                <ns1:getInputResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                        xmlns:ns1="http://DefaultNamespace">
                        <ns1:getInputReturn
xsi:type="xsd:string">$2500</ns1:getInputReturn>
                </ns1:getInputResponse>
        </soapenv:Body>
</soapenv:Envelope>

Gluing a Web Services Resource into mod_security

Blue Bank's web service uses the URL www.bluebank.example.com/axis/getBalance.jws. It's generally a good idea to create a rule set for this resource. To do so, Blue Bank has glued its resource into httpd.conf with:

<IfModule mod_security.c>
      SecFilterEngine On
      SecFilterDefaultAction "deny,log,status:500"
      # Other rules
# ------- Rules for web services --------------------------
      <Location /axis/getBalance.jws>
        SecFilterInheritance Off
        SecFilterDefaultAction "deny,log,status:500"
        SecFilterScanPOST On
        SecFilterCheckURLEncoding On
        SecFilterCheckUnicodeEncoding On
      </Location>
#---------------------------------------------------------------
</IfModule>

The following directive block applies filtering criteria for /axis/getBalance.jws. This adds the required placeholder for the defense of the web service. Placeholders go in the <Location> block.

# ------- Rules for web services --------------------------
<Location /axis/getBalance.jws>
        SecFilterInheritance Off
        SecFilterDefaultAction "deny,log,status:500"
        SecFilterScanPOST On
        SecFilterCheckURLEncoding On
        SecFilterCheckUnicodeEncoding On
</Location>
#---------------------------------------------------------------

There are two important directives here:

SecFilterInheritance  Off

This directive turns off all other rules and provides a clean space for a new rule set for the enclosing location only.

SecFilterScanPOST  On

Web services invocation methods go over POST. Hence, the next directive to enable is SecFilterScanPost to enable POST filtering.

With the above details in place, Blue Bank has deployed a shield in the form of mod_security. It also knows its defense target--the content of id, which clients pass to the web service over a SOAP envelope.

Defending Attack Vectors

As a first step to defend all incoming malicious requests, Blue Bank needs to trap the value of id to prevent a client from passing an invalid value. The SOAP request uses an XML tag to pass this id information to the internal web services code, looking something like:

<q1:getInput xmlns:q1="http://DefaultNamespace">
     <id xsi:type="xsd:string">12123</id>
</q1:getInput>

To filter the request, mod_security must have some way to read the value associated with the tag; in this case it is 12123. mod_security provides ways to trap a value passed through a POST request. One technique is to use a customized filter:

<Location /axis/getBalance.jws>
    SecFilterInheritance Off            
    SecFilterDefaultAction "deny,log,status:500"
    SecFilterScanPOST On
    SecFilterCheckURLEncoding On
    SecFilterCheckUnicodeEncoding On   
    SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>" chain
</Location>

The highlighted line traps the request made to id. POST_PAYLOAD intercepts the POST data block and tries to match the regular expression pattern (<\s*id[^>]*>). This regex pattern ensures that the tag for id exists. Only then does it proceed with the rest of the checks (because of the chain directive). In other words, if the tag id exists, mod_security continues with the next check.

If the sent POST request has an id contained in it, the server can process the information. However, a malicious client can modify this particular value to inject malicious content into it. There are four main popular attack vectors.

Attack vector 1: variable-length buffer injection

One of the major security concerns when passing a large buffer to a variable is that a large buffer may cause the application to misbehave and/or crash somewhere down the line during execution. The following rule defends the variable id against precisely this type of attack:

<Location /axis/getBalance.jws>
        SecFilterInheritance Off
        
        SecFilterDefaultAction "deny,log,status:500"
        SecFilterScanPOST On
        SecFilterCheckURLEncoding On
        SecFilterCheckUnicodeEncoding On
    
        SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>" chain
        SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>.{6,}</\s*id\s*>" 
		  "deny,status:500"
</Location>

In the above directive, the regular expression pattern <\s*id[^>]*>.{6,}</\s*id\s*> restricts the buffer to allow only a buffer of five characters. In order to ascertain the effect of the above directive block, Blue Bank can send across two requests, one that matches the buffer length set and the other that exceeds the buffer length set in the directive block.

POST /axis/getBalance.jws HTTP/1.0
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 576
Expect: 100-continue
Host: www.bluebank.example.com

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://www.bluebank.example.com/axis/getBalance.jws" xmlns:types="
http://www.bluebank.example.com/axis/getBalance.jws/encodedTypes"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
                <q1:getInput xmlns:q1="http://DefaultNamespace">
                        <id xsi:type="xsd:string">12123</id>
                </q1:getInput>
        </soap:Body>
</soap:Envelope>

...

HTTP/1.1 200 OK
Date: Mon, 03 Jan 2005 19:24:10 GMT
Server: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4
Set-Cookie: JSESSIONID=69C6540CC427A8B064C0795ADDFC20EA; Path=/axis
Content-Type: text/xml;charset=utf-8
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <soapenv:Body>
                <ns1:getInputResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                        xmlns:ns1="http://DefaultNamespace">
                        <ns1:getInputReturn
xsi:type="xsd:string">$2500</ns1:getInputReturn>
                </ns1:getInputResponse>
        </soapenv:Body>
</soapenv:Envelope>

In the above case, a buffer of five characters is passed, and the server sent a response with the value of $2500. Here's the response and request with a modified id of 121234 (six characters):

POST /axis/getBlalance.jws HTTP/1.0
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 577
Expect: 100-continue
Host: www.bluebank.example.com

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://www.bluebank.example.com/axis/getBalance.jws" xmlns:types="
http://www.bluebank.example.com/axis/getBalance.jws/encodedTypes"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
                <q1:getInput xmlns:q1="http://DefaultNamespace">
                        <id xsi:type="xsd:string">121234</id>
                </q1:getInput>
        </soap:Body>
</soap:Envelope>

...

HTTP/1.1 500 Internal Server Error
Date: Mon, 03 Jan 2005 22:00:33 GMT
Server: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4
Content-Length: 657
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
   <title>500 Internal Server Error</title>
  </head><body>
  <h1>Internal Server Error</h1>
  <p>The server encountered an internal error or misconfiguration and was
  unable to complete your request.</p>
  <p>Please contact the server administrator, you@example.com and inform
  them of the time the error occurred, and anything you might have done that
  may have caused the error.</p>
  <p>More information about this error may be available in the server
error
  log.</p>
  <hr />
  <address>Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d
mod_jk2/2.0.4
  Server  at 192.168.7.50 Port 80</address>
</body></html>

The mod_security module has rejected this request. Status 500 is the response received. This indicates that the request never hit the web services level. Blue Bank has succeeded, therefore, in providing a sound defense against any kind of buffer overflow, the most common and often ignored vulnerability.

Attack vector 2: metacharacter injection

Another major threat to input variables is the use of metacharacters such as %, single quote ('), and double quotes ("). These characters can cause SQL injection attacks to occur and may also cause unnecessary information leakage. Adopting the following strategy provides a sound defense against such attacks.

<Location /axis/getBalance.jws>
   SecFilterInheritance Off
        
   SecFilterDefaultAction "deny,log,status:500"
   SecFilterScanPOST On
   SecFilterCheckURLEncoding On
   SecFilterCheckUnicodeEncoding On
      
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>" chain
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>.{6,}</\s*id\s*>" 
     "deny,status:500"
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>.*[^a-zA-Z0-9][^<]*</\s*id\s*>" 
     "deny,status:500"      
</Location>

The regular expression pattern <\s*id[^>]*>.*[^a-zA-Z0-9][^<]*</\s*id\s*> denies an HTTP request if a variable's POST_PAYLOAD consists of any characters other than regular string characters. This inverted character set is an important technique in mod_security.

Here is the request and response sent using an id of 12'12:

POST /axis/getBalance.jws HTTP/1.0
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 576
Expect: 100-continue
Host: www.bluebank.example.com

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://www.bluebank.example.com/axis/getBalance.jws" xmlns:types="
http://www.bluebank.example.com/axis/getBalance.jws/encodedTypes"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
                <q1:getInput xmlns:q1="http://DefaultNamespace">
                        <id xsi:type="xsd:string">12'12</id>
                </q1:getInput>
        </soap:Body>
</soap:Envelope>

...

500 Internal Server Error
HTTP/1.1 500 Internal Server Error
Date: Mon, 03 Jan 2005 22:00:33 GMT
Server: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4
Content-Length: 657
Connection: close
Content-Type: text/html; charset=iso-8859-1

This attack also failed, and mod_security caught it.

Attack vector 3: SQL injection

It is also possible to inject SQL statements in variables. Concatenating together many SQL statements is possible. If your application does not sanitize its input, malicious clients can append additional SQL statements to existing SQL queries, often with disastrous consequences. Blue Bank has blocked SQL injection attacks by adding the following directives:

<Location /axis/getBalance.jws>
   SecFilterInheritance Off
   SecFilterDefaultAction "deny,log,status:500"
   SecFilterScanPOST On
   SecFilterCheckURLEncoding On
   SecFilterCheckUnicodeEncoding On
 
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>" chain
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>.{6,}</\s*id\s*>" 
     "deny,status:500"
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>.*[^a-zA-Z0-9][^<]*</\s*id\s*>" 
     "deny,status:500"
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>.*select.+from[^<]*</\s*id\s*>" 
     "deny,status:500"
</Location>

The highlighted regular expression matches the "select * from . . ." clause and, if matched, will send back status 500 as in the previous case. Similarly, you can add SQL statements for delete, update, and so on. As shown in previous sections, mod_security will defend against these attacks, returning a 500 error.

Attack vector 4: SOAP fault code disclosure

One of the major sources of information in web services is the fault code. A forced error on the server can create a fault code. Here's the request and response from a malicious user probing Blue Bank by sending a request with the character a in the id variable instead of an integer:

POST /axis/getBalance.jws HTTP/1.0
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 569
Expect: 100-continue
Host: www.bluebank.example.com

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://www.bluebank.example.com/axis/getBalance.jws" xmlns:types="
http://www.bluebank.example.com/axis/getBalance.jws/encodedTypes"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
                <q1:getInput xmlns:q1="http://DefaultNamespace">
                        <id xsi:type="xsd:string">a</id>
                </q1:getInput>
        </soap:Body>
</soap:Envelope>

...

500 Internal Server Error
HTTP/1.1 500 Internal Server Error
Date: Tue, 04 Jan 2005 16:22:14 GMT
Server: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4
Set-Cookie: JSESSIONID=1CAF4CD0ED0F38FB40ECBC7BDAB56C75; Path=/axis
Content-Type: text/xml;charset=utf-8
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <soapenv:Body>
   <soapenv:Fault>
        <faultcode>soapenv:Server.userException</faultcode>
        <faultstring>java.lang.NumberFormatException: 
		  For input string:"a"</faultstring>
   <detail/>
   </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

As shown in the response, the fault code may disclose critical internal information. That's reason enough to define and apply filters. Blue Bank can fix this by applying the following rules:

<Location /axis/getBalance.jws>
   SecFilterInheritance Off
        
   SecFilterDefaultAction "deny,log,status:500"
   SecFilterScanPOST On
   SecFilterCheckURLEncoding On
   SecFilterCheckUnicodeEncoding On
     
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>" chain
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>.{6,}</\s*id\s*>" 
     "deny,status:500"
   SecFilterSelective POST_PAYLOAD "<\s*id[^>]*>.*[^a-zA-Z0-9][^<]*</\s*id\s*>" 
     "deny,status:500"
     
   SecFilterScanOutput On
   SecFilterSelective OUTPUT "faultcode" "deny,status:500"
</Location>
SecFilterScanOutput On

This directive scans an output data block and applies defined filters.

SecFilterSelective OUTPUT "faultcode" "deny,status:500"

This directive blocks outgoing traffic that contains fault codes. If the attacker sends the ill-formed request again with a in the integer field, he will receive a response more like:

HTTP/1.1 500 Internal Server Error
Date: Mon, 03 Jan 2005 22:00:33 GMT
Server: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4
Content-Length: 657
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
   <title>500 Internal Server Error</title>
  </head><body>
  <h1>Internal Server Error</h1>
  <p>The server encountered an internal error or misconfiguration and was
  unable to complete your request.</p>
  <p>Please contact the server administrator,  you@example.com and inform
  them of the time the error occurred, and anything you might have done that
  may have caused the error.</p>
  <p>More information about this error may be available in the server
error 
  log.</p>
  <hr />
  <address>Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d
mod_jk2/2.0.4
  Server  at 192.168.7.50 Port 80</address>
</body></html>

mod_security, properly configured, has also defended against this attack.

Conclusion

mod_security may seem like just another tool in the security firmament, but it has a subtle advantage over other security tools already available. While providing intrusion detection and defense capabilities at the HTTP layer, mod_security also allows POST_PAYLOAD filtering capabilities.

However, the advantage mod_security offers is in allowing developers and web administrators to defend web services without actually modifying their source code. This doesn't make shabby code tolerable; it simply means that an organization can mount an additional effective defense of its web services without having to run through numerous lines of code.

This article focuses on just one of the techniques for securing web services, and an effective one too. Feel free to choose your own techniques of defending web services.

For more information on mod_security, see Introducing mod_security, mod_security quick examples, and HOWTO: Enhancing Apache with mod_security.

Shreeraj Shah is the founder of Blueinfy, a company that provides application security services.


Return to the Security DevCenter.

Copyright © 2009 O'Reilly Media, Inc.