Securing Web Services with mod_securityby Shreeraj Shah
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:
- Variable-length buffer injection
- Meta character injection
- SQL injection
- SOAP fault code disclosure
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.
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
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
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
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>