Securing Web Services with mod_security
Pages: 1, 2, 3
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.
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 2 of 2.
-
Keeping it simple
2005-06-14 06:45:22 rparkin [Reply | View]
Thanks for explaining mod_security!
As a wannabe Perl guy, I appreciate the power and flexibility of regular expressions. mod_security seems to be an elegant and relatively simple solution to a complicated problem.
I don't think the point is to avoid having to build security into applications from the ground up. After all, the same regexes you'd use in mod_security would work just as well in the application's input validation and probably ought to be there as well. Nothing wrong with double-checking input where potential security issues are concerned.
But I think mod_security is more than just a stopgap measure.
First of all, it is a security wrapper that can be used to protect web apps that you didn't write yourself and haven't had time to pick apart for flaws. Imagine your boss handing you an app written by a vendor and telling you to get it up and running ASAP. That never happens, right? Enter mod_security.
Second, why wouldn't you want to stop attacks as early in the session as possible? It means you can free up resources to handle the next legitimate request that much faster.
The only real drawback is what we all know: that complex regular expressions can be very tricky to implement. But that's another reason I like mod_security's post payload functionality. You can filter input progressively through a ruleset of many regular expressions rather than having to craft the "one true regex" that catches everything.
I'll definitely keep mod_security in mind.



but i want to ask .. can I use Mod_Security .. or any Idea to prevent spamming ?
I have a server and my customers sending a huge sum of mails to other members in their forums or mailing lists ...
So , Can I configuer the mail() function on the server to prevent sending mails ??
I want it to send only 10 mails by once ..
is their any Idea ?
waiting
-Ahmed,