Security DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement




Securing Web Services with mod_security
Pages: 1, 2, 3

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.

Pages: 1, 2, 3

Next Pagearrow






Sponsored by: