将Web服务与mod_security结合起来
Blue银行的web服务使用www.bluebank.example.com/axis/getBalance.jws的URL。为这个资源创建一套规则通常一个不错的主意。为达此目的,Blue银行将此资源通过以下方式加入到httpd.conf:
<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
下面的指令块为/axis/getBalance.jws应用了过滤标准。为了保护web服务它添加了必要的规则。这些规则在<Location块中,如下:
# ------- Rules for web services --------------------------
<Location /axis/getBalance.jws
SecFilterInheritance Off
SecFilterDefaultAction "deny,log,status:500"
SecFilterScanPOST On
SecFilterCheckURLEncoding On
SecFilterCheckUnicodeEncoding On</Location
#---------------------------------------------------------------
在这里有两个重要的指令:
SecFilterInheritance Off
这个指令关闭其他所有规则,为新的location建立一套规则创建一个干净的空间。(译者注:初始化,建立新空间)
SecFilterScanPOST On
由于web服务的方法调用是通过POST,所以这个指令是打开POST过滤器。
有了上面的配置,Blue Bank已经在mod_security中部署了一个“护盾”(译者注:防火墙)。该“护盾”也知道它的防护目标――客户端通过SOAP封套发送的id的内容。
防范攻击
作为防护所有恶意请求的第一步,Blue银行需要限制从客户端发送的id的值,防止传来无效值。SOAP请求用XML标签将id信息发送到web服务的代码中,像如下这样:
<q1:getInput xmlns:q1="http://DefaultNamespace"
<id xsi:type="xsd:string"12123</id</q1:getInput
为了过滤该请求,mod_security必须有一些途径去读取与标签相关的值(在这里标签是id);这个例子中的值是12123,mod_security提供一些途径限制通过POST请求发送的值。其中的一个方法就是使用自定义过滤器:
<Location /axis/getBalance.jws
SecFilterInheritance Off
SecFilterDefaultAction "deny,log,status:500"
SecFilterScanPOST On
SecFilterCheckURLEncoding On
SecFilterCheckUnicodeEncoding On
SecFilterSelective POST_PAYLOAD "<\s*id[^]*" chain</Location
上面标示出来的行对请求中的id进行限制。POST_PAYLOAD截取POST数据块并与正则表达式(<\s*id[^]*)进行匹配。该正则表达式确保id标签存在,当存在的情况下才进行其余的检查。换句话说,如果id标签存在,mod_security继续下一个检查。
如果发送的POST请求中存在一个id,服务器能够执行信息。然而,一个恶意的客户端能够修改这个值加入恶意内容。有四种最流行的攻击方式。
攻击方式1:变量长度缓冲区注入(译者注:缓冲区溢出)
当把一个大的缓冲数据传给一个变量时可能会引起应用程序运行不正常或者在执行的时候“宕”掉的安全隐患。下面的规则将保护id变量免受此类攻击:
<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
在上面的指令中,正则表达式<\s*id[^]*.{6,}</\s*id\s*限制缓冲变量的长度为5个字符。为了检查上面的代码块是否起作用,Blue银行可以发送两个请求,一个请求符合约束,另一个越界。
POST /axis/getBalance.jws HTTP/1.0Content-Type: text/xml; charset=utf-8SOAPAction: ""Content-Length: 576Expect: 100-continueHost: 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:Bodysoap: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 OKDate: Mon, 03 Jan 2005 19:24:10 GMTServer: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4Set-Cookie: JSESSIONID=69C6540CC427A8B064C0795ADDFC20EA; Path=/axisContent-Type: text/xml;charset=utf-8Connection: 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:getInputResponsesoapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://DefaultNamespace"
<ns1:getInputReturnxsi:type="xsd:string"$2500</ns1:getInputReturn
</ns1:getInputResponse
</soapenv:Body</soapenv:Envelope
在上面的例子中,将一个包含5个字符的缓冲数据传给web服务,服务收到后发回一个响应值为$2500。下面的例子将更改12123这个数据为121234,新的数据有6个字符,将得到一个新的响应信息,如下:
POST /axis/getBlalance.jws HTTP/1.0Content-Type: text/xml; charset=utf-8SOAPAction: ""Content-Length: 577Expect: 100-continueHost: 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:Bodysoap: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 ErrorDate: Mon, 03 Jan 2005 22:00:33 GMTServer: Apache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7d mod_jk2/2.0.4Content-Length: 657Connection: closeContent-Type: text/html; charset=iso-8859-1<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"<html<head
<title500 Internal Server Error</title
</head<body
<h1Internal Server Error</h1
<pThe server encountered an internal error or misconfiguration and was
unable to complete your request.</p
<pPlease 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
<pMore information about this error may be available in the servererror
log.</p
<hr /
<addressApache/2.0.50 (Unix) mod_ssl/2.0.50 OpenSSL/0.9.7dmod_jk2/2.0.4
Server
at 192.168.7.50 Port 80</address</body</html
mod_security模块拒绝了该请求。返回500状态。这说明请求根本没有到达web服务层。Blue 银行成功地防范了最常见和常常被忽略的缓冲区溢出攻击。(译者注:HTTP定义的500状态是服务器执行错误)
第二种攻击:元字符注入
另外一个主要的针对输入变量的威胁来自于使用像%,单引号(’),双引号(”)。这些字符会导致SQL注入攻击,并且可能会导致不必要的信息泄漏。采用下面的策略将保护web服务防范此类攻击。
<Location /axis/getBalance.jws
SecFilterInherita