怎么样使用mod_security增强web安全性?

怎么样使用mod_security增强web安全性?

用mod_security增强web安全性
一孔之见
2003.07.11
前几天看了《SecuringApache:
Step-by-Step》,里面粗略的介绍了一下mod_security的使用,于是自己看了看资料,把mod_security的使用翻译过来,算是给那些不喜欢看E文的“懒汉”一点点便利。
介绍
ModSecurity是一种用于web程序的保护和检测引擎。它采用内嵌入web服务器,防止黑客的攻击,充当了有力的保护桑具有以下特点:
l请求过滤:当请求提交时,在对提交的数据被web服务器或其他程序使用之前进行分析。
l避免逃避技术:在对数据进行分析之前将路径和参数一般化,以避免遗漏。
l理解HTTP协议:由于引擎能够理解HTTP协议,故能进行特殊的细粒度的检查
lPOST数据分析:引擎将截取采用POST方式传递的数据
l审计纪录:能够详细记录每一组请求的内容(包括POST的内容)以备日后详细分析
lHTTPS过滤:由于引擎内嵌入服务器,所以可以访问解密后的请求数据

如何安装
在安装之前你需要选择适合自己的安装方式。首先你需要选择是通过CVS安装最新版本还是安装最新的稳定版本。如果你选择稳定版本,那么你可以从二进制文件安装或是通过编译源代码来安装。最后,当你编译源代码的时候,你需要选择将模块静态编译进web服务器还是采用共享库模块的方式安装。你可以在http://www.modsecurity.org/download/;
下载最新的发行版本。下载之后我们主要讨论如何从原文件编译。我们可以采用的第一种方式是DSO,要安装成DOS非常容易,并且安装过程在两个版本的apache中都是一样的:解压缩文件,然后输入一下命令进行编译
/apachehome/bin/apxs–ciamod_security.c
这里的/apachehome指的是apache的安装路径,多为/usr/local/apache,然后我们重启apache就可以让软件生效了
/apachehome/bin/apachectlrestart
第二种安装方式就是与apache一起静态编译,在两个版本的apache上面安装有所不同。首先介绍与apache
1.x一起静态编译:首先将文件mod_security.c拷贝到/src/modules/extra目录,然后在configure时加入以下两条
--activate-module=src/modules/extra/mod_security
--enable-module=security
最后像以前一样编译apache。
与apache2.x一起编译稍微麻烦一点:
1.配置apache以包含mod_security
./configure–prefix={myprefix}–with-module=mappers:security
2.将文件mod_security.c拷贝到modules/mappers/
3.编辑文件modules/mappers/modules.mk,加入以下行
mod_security.la:mod_security.lo
${MOD_LINK}mod_security.lo
在”static=”后面加上下面的内容
static=mod_negotiation.lamod_security.lamod_dir.la…
4.编译
make
可以通过./httpd–l来检查时候将该模块编译进了服务器,输出中如果包含了mod_security.c则表明编译进了服务器,接下来我们开始安装
makeinstall
最后重启服务器/apachehome/apachectlrestart
以上介绍的是从源代码安装,下面介绍从二进制文件安装
apache1.x
将文件mod_security.so或是mod_security.dll拷贝到libexec并在httpd.conf中加入
LoadModulesecurity_modulelibexec/mod_security.so
apache2.x
将文件mod_security.so或mod_security.dll拷贝到modules/并在httpd.conf中加入
LoadModulesecurity_modulemodules/mod_security.so

配置
打开/关闭过滤器
过滤器缺省情况下是关闭的,要启用该功能,你可以打开它
SecFilterEngineOn
POST扫描
POST载荷扫描缺省情况下是关闭的,要启用该功能,你可以打开它
SecFilterScanPOSTOn
缺省行为
当提交的请求满足某一过滤器时,需要采取一定的行为。个别的过滤器都有自己的行为,但实际上,你想要为所有的过滤器定义一系列的行为。你可以通过定义SecFilterDefaultAction来进行配置。
SecFilterDefaultAction“deny,log,status:404”
过滤器继承
对父文件夹定义的过滤器通常被子文件夹继承。这一行为在大多数情况下是可以接受的(也是必需的),但是并不总是适用。有时你需要放松站点某些部分的检查。可以使用以下配置
SecFilterInheritanceOff
URL编码有效性
特殊字符在URL中传输之前必须经过编码。任何字符都可以用%XY的形式替代,这里的XY是十六进制编码的。十六进制数只有从A到F的字母,但有时黑客使用其他字母来愚弄编码算法。Mod_security检查所有编码以保证其有效性,配置语句为:
SecFilterCheckURLEncodingOff
注意,当使用”multipart/form-data”编码(文件上传)时,不会对POST的内容进行检查
字节范围检查
你可以强制要求请求的内容包括一定字节范围。这在避免堆栈溢出攻击方面有一定的效果(因为它们通常包含随机的),如果想只允许32到126字节的内容,可以使用以下配置
SecFilterForceByteRang32126
缺省的范围是从0到255,即所有范围都被允许。注意:这一选项不会检查使用”multipart/form-data”编码的POST内容。
允许他人看见mod_security
通常,入侵者不能判断web服务器是否运行了mod_security。你可以通过发送定制的消息或特殊的HTTP编码(如406)来讲自己阻挡在门外。如果你想隐藏信息,那么最好是发送HTTP
500,含义是”InternalServerError”(服务器内部错误),入侵者受到这个消息之后会认为web服务器已经崩溃了。
还有一种解决方案就是不隐藏你运行了mod_security。按道理,如果入侵者看见这些消息之后就知道你在这上面花了一番心思,要渗透非常困难。于是他们就会转而寻找其他的防守脆弱的目标,也有可能坚定他们的决心,挑起他们的意志:(
缺省情况下,apache会对它提供的每一个请求返回自己的信息。Mod_security则会对请求保持沉默,但是你可以通过以下配置让其他人看见mod_security的信息
SecServerResponseTokenOn
其结果看起来像这样:
[ivanr@wkxconf]$telnet08080
Trying0.0.0.0...
Connectedto0.
Escapecharacteris^].
GET/HTTP/1.0
HTTP/1.1406NotAcceptable
Date:Mon,19May200318:13:51GMT
Server:Apache/2.0.45(Unix)mod_security/1.5
Content-Length:351
Connection:close
Content-Type:text/html;charset=iso-8859-1




NotAcceptable


Anappropriaterepresentationoftherequestedresource/couldnotbefound
onthisserver.



Apache/2.0.45(Unix)mod_security/1.4.2Serveratwkx.dyndns.orgPort
80


Connectionclosedbyforeignhost.
应当注意的是
apache自己支持两种运行时参数:ServerTokens和ServerSignature。使用这两个参数你可以完全隐藏服务器信息,而不管SecServerResponseToken是否打开。
调试
使用SecFilterDebug选择一个储存信息的文件。如果参数不是以斜线/开始,将使用apache的主目录。
SecFilterDebuglogs/modsec_debug_log
用于控制调试等级的参数是SecFilterDebugLevel
SecFilterDebugLevel4
调试等级为:
0.无调适
1.重要事件
2.信息
3.更详细的信息
请求过滤器
当mod_security启用时,每一条入站的请求都在使用之前会被截取并分析。分析首先采用一系列的内置规则来检查请求内容的有效性。这些检查可以使用配置参数来进行设定,正如你看见的那样。分析的另外部分由用户自定义的请求需要满足的规则构成。无论何时一条主动规则匹配时,都会采取特定的行为。
简单过滤器
mod_security提供的最简单的过滤器形式的确相当简单,看起来像这样
SecFilterKEYWORD
对每一次像这样的简单过滤器,mod_security将要检查请求中的关键字。检查的范围相当广,这将应用到请求的第一行(看起来像这样”GET/
index.php?parameter=valueHTTP/1.0”)。对于POST请求,将搜索body部分(如果设置了SecFilterScanPOST
On)
路径规则化
过滤器不会应用于原始的请求数据,而是应用于规则化之后的数据。我们这样做是因为入侵者可以(并且多半)使用各种逃避手段来避免检测。例如,你可能想要设置一个过滤器来检测执行shell命令
SecFilter/bin/sh
但是入侵者可以使用/bin/./sh来绕过过滤器。当前版本的mod_security可以进行以下转换:
。减少/./为/
。检验URL编码(可选)
。只允许一定范围的字节(可选)
。解码URL
。减少//为/
正则表达式
记住最简单的过滤器设置,看起来是这样的
SecFilterKEYWORD{ACTIONS}
在定义关键字的时候不仅仅局限于一个词,你可以使用能够想到的任何正则表达式。为了充分利用这款强有力的工具,你需要对正则表达式有一定的了解,我建议你从以下的资源开始:
。Perl正则表达式http://www.perldoc.com/
。精通正则表达式http://www.oreilly.com/catalog/regex/
。Google搜索引擎关于正则表达式的搜索http://www.google.com
反转表达式
如果感叹号是一条正则表达式的第一个字符,过滤器将其以反义对待。例如:
SecFilter“!php”
将对拒绝所有不包含”php”的请求。
高级过滤器
虽然SecFilter能够让你快速上手,但是你会很快发现这种搜索太宽泛并且不能很好的工作。可以使用另外一个参数
SecFilterSelectiveLOCATIONKEYWORD{ACTION}
它允许你精确选择搜索匹配。KEYWORD和ACTIONS与SecFilter中是一样的,LOCATION位需要进一步的解释。参数LOCATION由一系列管道符号分隔的位置标识构成,例如
SecFilterSelective“REMOTE_ADDR|REMOTE_HOST”KEYWORD
这样就只会搜索客户端的IP地址和主机名。可用的位置包括所有的CGI变量,和一些其他的变量,以下是完整的列表:
lREMOTE_ADDR
lREMOTE_HOST
lREMOTE_USER
lREMOTE_IDENT
lREQUEST_METHOD
lSCRIPT_FILENAME
lPATH_INFO
lQUERY_STRING
lAUTH_TYPE
lDOCUMENT_ROOT
lSERVER_ADMIN
lSERVER_NAME
lSERVER_ADDR
lSERVER_PORT
lSERVER_PROTOCOL
lSERVER_SOFTWARE
lTIME_YEAR
lTIME_MON
lTIME_DAY
lTIME_HOUR
lTIME_MIN
lTIME_SEC
lTIME_WDAY
lTIME
lAPI_VERSION
lTHE_REQUEST
lREQUEST_URI
lREQUEST_FILENAME
lIS_SUBREQ
还有一些特殊的位置:
lPOST_PAYLOAD过滤POST请求的有效载荷
lARGS过滤参数,同“QUERY_STRING|POST_PAYLOAD”
lARGS_NAMES仅变量/参数名
lARGS_VALUES仅变量/参数值
lHTTP_header搜索请求头部
lENV_variable搜索环境变量
lARG_variable搜索请求变量/参数
参数过滤器
ARG_variable位置名支持反义用法
SecFilterSelective“ARGS|!ARG_param”KEYWORD
将搜索所有参数,除了param