Copyright © 2002-2005 Ivan Ristic <ivanr@webkreator.com> http://www.modsecurity.org
中文版: 我爱臭豆腐,sakulagi,Alan.Jin http://www.chinaunix.net
中文版备注:
随着使用apache得人越来越多,和使用web服务得广泛.web服务器得安全问题也是一个至关重要得问题.但是在国内真正能够做web服务安全得感觉并不是很多(实际上也有很多是抄袭免费软件的概念和技术).而且即使是有得话相对来讲成本也是很高的.所以我希望能够找到一个价格相对低廉而且又有效的方法来防护web服务的安全.
当初打算翻译这个的另外一个原因是,经常浏览国外的安全方面的网站和一些外国站点.发现在apache上面安装ModSecurity 或者是介绍web安全的人100%或者是说99.99%都在介绍和使用这个插件.但是在国内的资料上面并没有看到这些东西或者是一带而过了.我本人外语不好当然了中文的水平也不好.但是我想这么好的一个软件应该叫更多的人熟悉和了解.我希望以后在有朝一日能够叫每个apache的服务器都安装这个插件用来抵御来自界的攻击.但是这个只是一个理想或者是梦想.
这里要非常感谢sakulagi,Alan.Jin 他们两个人的外语都比我好.特别是sakulagi 英文水平和中文水平都很好.如果大家要感谢的话应该是多感谢他们.我只是想他们两个人推荐这里这个软件和引入了要翻译这个手册的想法.
最后想说的是安装了这个软件并不是一个大力丸能够防止任何攻击和渗透.任何软件和工具都不是无敌的.都是需要管理员精心的配置和发挥他的最大的功效.
介绍
Modsecurity 是一个开放原代码的入侵检测和防护引擎,用来保护Web应用程序.他同样和可以当作一个Web应用程序防火墙.它嵌入到Web服务器中,担当一个强大的保护伞-保护来自应用程序的攻击.
ModSecurity 和web服务器结合,增强web服务器抗攻击的能力.一些只得关注的功能说明:
l 过滤请求:在web服务器或者其他模块获得handled之前, 按照原来的样子分析进入的请求.(严格的说,在这种嵌入式的操作里面,有一些操作在没有到达ModSecurity之前不可避免的进行了一些操作.)
l Anti-evasion 技术: paths and parameters are normalised before analysis takes place in order to fight evasion techniques.
l 了解HTTP协议:引擎获得了http的协议后,将进行非常详细的颗粒过滤.例如,它可以查看任何一个单独的参数,或者是制定的cookie值.
l POST 有效负载分析:这个引擎能够截取传送的内容使用POST方法.
l 审计记录:能够详细的记录每一个请求(包括POST)可以被用在法律分析上.
l HTTPS 过滤:当这个引擎被嵌入到web服务器中后,可以有权访问解密后的数据请求.
l 过滤被压缩的内容:和上面一样,安全引擎可以有权访问到被解压缩后的内容.
ModSecurity 能够被用于发现攻击,或者是发现和阻止攻击.
许可
ModSecurity is available under two licenses. Users can choose to use the software under the terms of the GNU General Public License (http://www.gnu.org/licenses/gpl.html), as an Open Source / Free Software product. Alternatively, a variety of commercial licenses is available: end-user licenses for individual or site-wide deployment, OEM licenses for closed-source distribution with applications, web servers, or security appliances. For more information on commercial licensing please contact Thinking Stone Ltd:
Thinking Stone Ltd
Tel: +44 845 0580628
Fax: +44 870 7623934
http://www.thinkingstone.com
contact@thinkingstone.com
感谢
如果是没有这么多好人建立了Apache web服务器,和一些好人花费大量的时间来营造Apache的模块,我将不能经常学习Apache的模块设计.我特别感谢设计和编写mod_rewrite.的人们.
联系
ModSecurity 的开发是由Ivan Ristic 和 Thinking Stone.欢迎注释和重要反馈.请发邮件到ivanr@webkreator.com
备注:
请不要发给我关于技术问题的邮件这个邮件地址是我私人信箱.我不能使用我的私人时间来处理这些技术问题.用户自己可以从mail archives寻找答案.如果你需要快速的回答问题和你想保证反映时间请考虑从Thinking Stone公司购买商业服务.
安装
在你安装之前你需要选择适合你自己的安装方法.第一你需要选择是否安装最新的版本从ModSecurity 的CVS目录当中(里面有最新的特性,但是不稳定).或者是安装最新的稳定版本(推荐).如果你选择稳定版的话,你可以安装ModSecurity 的二进制文件.它已经被从原代码编译完成.
下面的一些内容可以帮助你更好的选择一个适合自己的方法来安装它.
通过CVS
如果你想要最新版本的模块话可以从CVS库中得到.可以从一个web站点获得从最近的一个稳定版本的被改变的列表(在CHANGES这个文件中).ModSecurity 的CVS库存放在SourceForge(http://www.sf.net).你可以直接通过这个地址访问和查看http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/mod-security/.
下载源程序到你的计算机.需要执行下面两个命令:
cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/mod-
security login
cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/mod-
security co mod_security
第一行是你使用anonymouse用户登陆,第二行是下载全部的可用的文件从CVS库中.
每夜快照下载
如果是不喜欢CVS,但是你还想要最新的版本你可以下载最新的nightly tar包从下面的地址:
http://www.modsecurity.org/downl ... ity-snapshot.tar.gz 新功能被一一的加入到了mod_security中,用来测试在每一次改变之后.这方法可以确保从CVS上面有永远可用的版本下载.
稳定版下载
可以从http://www.modsecurity.org/download/ 下载到稳定的版本.如果你不下载源代码分发的版本时.不时的可以有一些二进制的分发.如果有他们在下载页面的列表上.
从源程序安装
从源程序安装有两个方法:一个是将模块和web 服务器编译到一起去.或者是编译mod_security.c 成动态共享对象(DSO).
DSO
DSO安装方法非常容易,安装方法有两种流派在Apache的安装方法中.第一要解压缩文件到一个地方(必须要作的),编译模块的命令:
/apachehome/bin/apxs -cia mod_security.c
在这之后你需要关闭和从新启动Apache 服务(如果你尝试从新启动它你可能会segfault)
/apachehome/bin/apachectl stop
/apachehome/bin/apachectl start
我知道有一些人使用的平台上没有apxs这个工具安装到系统上.这个工具在一些Unix的平台上的版本是独立的包.这个问题出现在安装的时候不是缺省安装.解决这个问题的方法是从你的软件厂商那里查找如何建立自定义的Apache模块.(在一些RedHat 平台上你需要安装http-devel 包后就有了apxs这个应用程序).
静态安装用于Apache 1.x
在静态的编译模块时,这个程序将被内置到web服务器本身.这种方法能够快一点的执行但是这个编译方法有更多的难度(以后的维护).
释放这个软件包后将mod_security.c 这个文件复制到Apache源代码目录src/modeules/extra 中.
更改configureation 脚本激活这个新模块:
# ./configure /
/
--activate-module=src/modules/extra/mod_security /
-–enable-module=security
正常的编译,安装和启动你的web服务器.
安装二进制版本
在一些环境下,你想要安装二进制的模块.此刻我只是建立了Windows 二进制版本在下载的地方.在每一个版本中有两个DSO库文件,在每一个主要的Apache的分支中.在这些文件中选择一个适合你的Apache 的版本.参考下列描述:
Apache 1.x
复制mod_security.so (Unix 系统) 或者mod_security.dll (Windows 系统)到libexec/目录下(这个文件架是Apache 安装的目录,不是源代码目录).添加下面内容到httpd.conf :
LoadModule security_module libexec/mod_security.so
根据你现在的配置文件(你需要确认你的配置文件中模块的加载顺序)他需要使用AddModule 指令来激活模块.指令如下:
AddModule mod_security.c
在大多数的时候他不需要添加这个在配置文件中.但是推荐你将mod_security 加入到最后的module链表中(但是在实际当中,如果你打算使用内部的chroot功能的话必须要添加这个在配置文件中).可以在”在chroot 环境下模块顺序要求(Apache 1.x)”有详细的介绍.
Apache 2.x
复制mod_security.so (Unix系统)或者mod_security.dl (Windows 系统)到modules/ 目录中(这个目录是Apache 的安装目录,不是源程序目录).添加下来内容到httpd.conf配置文件中.:
LoadModule security_module modules/mod_security.so
配置
ModSecurity 配置指令可以直接被添加到你的配置文件中(典型配置是在httpd.conf文件中).但是他不一定确信这个模块被激活或者是禁止在web服务器启动的时候 它通常是将配置信息放在容器内.在没有激活这个模块的时候,它可以允许Apache跳过这个配置容器.
# mod_security configuration directives
# ...
自从Apache允许将一组配置数据保存在一个(例如modsecurity.conf)配置文件中,然后被httpd.conf 使用Include 方法调用.:
Include conf/modsecurity.conf
关闭和开启过滤
过滤引擎缺省是关闭的。需要开启请求的监视的话,可以把这个指示加入配置文件中:
SetFilterEngine On
这个参数支持的值包括:
On - 分析每个请求
Off - 无动作
DynamicOnly - 只分析运行时动态生成的请求。使用这个选项可以防止Web服务器使用宝贵的CPU资源检查对静态文件的请求。希望了解ModSecurity如何判断哪些请求是动态生成的,可以参考“选择日志中记录什么”。
POST扫描
请求体的有效载荷(或者POST有效载荷)扫描缺省是禁止的。需要使用的话,需要手工打开:
SetFilterScanPOST On
mod_security 对请求体支持两种编码方式:
application/x-www-form-urlencoded - 用来传输表单数据
multipart/form-data - 用于文件传输
其他的编码没有被大多数web应用程序用到。为保证只有使用这两种编码方式的请求被web服务器接受,需要在配置文件中加入下列行:
SecFilterSelective HTTP_Content-Type /
"!(^$|^application/x-www-form-urlencoded$|^multipart/formdata;)"
动态关闭缓存
可以关闭基于每个request的POST有效载荷扫描。如果环境变量MODSEC_NOPOSTBUFFERING被定义,ModSecurity不会进行POST有效载荷扫描。例如,要关闭文件上传的POST有效载荷的缓存,可以:
SetEnvIfNoCase Content-Type /
"^multipart/form-data;" "MODSEC_NOPOSTBUFFERING=Do not buffer
file uploads"
对变量MODSEC_NOPOSTBUFFERING的赋值会写在debug日志里,因此可以在这里记录你关闭缓存的原因。
块状传输编码
HTTP协议支持一种在事先不知道有效载荷大小的情况下传输请求的方法。请求体会包装成大小固定的块传输。这就是“块状传输编码”名字的由来。ModSecurity目前不支持分快请求。当一个请求按块状编码的时候,它的请求体会被忽略。到目前我所知的浏览器还没有使用块状编码来传输请求的。尽管Apache对某些操作支持这种编码,很多模块并不支持。
如果不加注意,这可能会为攻击者提供机会来散布恶意的有效载荷。可以在配置文件中加入下面这行来阻止攻击者利用这个漏斗:
SecFilterSelective HTTP_Transfer-Encoding "!^$"
这个改动不会影响使用块状传输编码来发送反溃
缺省动作列表
只要一个请求能够匹配一条规则,一个或多个动作就会发生。每个单独的过滤器都可以有自己的动作,但是为所有的过滤器定义一套缺省的动作会更方便。(如果需要你总可以定义pre-rule动作。)你可以用SecFilterDefaultAction这个配置指示来定义缺省动作。比如,下面这句会配置引擎使之记录每一条匹配的规则,然后用状态码404来拒绝请求:
SecFilterDefaultAction "deny,log,status:404"
SecFilterDefaultAction指示值接受一个参数,一个逗号分隔的动作列表。在这里指定的动作会作用在每一个匹配的过滤器上,除非这个规则自己已经定义了自己的动作列表。
在1.8.6中,如果你指定了一个非致命的缺省动作列表(一个不会导致请求被拒绝的类表,比如log, pass)这样的列表在初始化阶段会被忽略。初始化阶段是被设计用来收集请求的信息的。允许非致命的动作会导致请求的部分的某些片断的丢失。因为这些信息在内部处理的时候是必需的,这样的动作不被允许。如果你希望ModeSecurity在“监测”模式下工作,需要禁止所有的隐式校验(URL编码校验,Unicode编码校验,cookie格式校验,字节范围限制)。
隐式校验
在1.8.6中,隐式请求校验(如果配置了的话)只在请求处理开始阶段被采用。在那之后,只有标准化动作会被采用。这个修改允许更好的防护(请求报头现在会在开始时被自动检查)。同时允许“监测”模式的规则。
过滤器的继承
在父目录中定义的过滤器通常会被嵌套的Apache配置所继承。这个行为通常是可接受的(而且是必需的)。但并不总是这样。有时候你需要在网站的某些部分放松检查。使用SecFilterInheritance指示
SecFilterInheritance Off
可以通知ModeSecurity来忽视父过滤器这样你可以从报头开始定义规则。这个指示只影响规则。配置总是从父上下文中继承,但是你可以使用合适的配置指示来覆盖继承来的设置。
配置和规则的继承缺省总是激活的。如果你在一个禁止的继承的配置上下文下面有另一配置上下文,你需要继续禁止继承,那么必须显式的再禁止一次。
URL编码校验
特殊字符在通过URL传输之前需要被编码。任何一个字符都可以用%XY这种方式来编码。XY是一个十六进制的字符编码(参考http://www.rfc-editor.org/rfc/rfc1738.txt获得更多细节)十六进制数字只允许字母A到F,但是攻击者有时使用其他字母来欺骗解码算法。ModSecurity检查所有的编码,校验他们是否合法。
你可以通过下列方法打开URL编码校验功能:
SecFilterCheckURLEncoding On
在使用multipart/form-data编码(文件上传)的时候,这个指示并不检查POST的有效载荷。因为URL编码不在这种编码中使用,所以这样做不是必要的。
Unicode编码校验
和其他很多的特性一样,Unicode编码校验缺省是禁止的。如果你的应用程序或是操作系统接受/理解Unicode,你应该开启这个选项。
关于Unicode和UTF-8编码的更多细节可以在RFC2279(http://www.ietf.org/rfc/rfc2279.txt)中找到。
SecFilterCheckUnicodeEncoding On
这个特性假定使用的是UTF-8编码并检查3种类型的错误:
缺失字节。 UTF-8支持2字节到6字节的编码。ModeSecurity可以定位一个或多个字节的缺失。
非法编码。大多数字符中的两个最重要的位被假定固定为0x80。攻击者利用这个来破坏Unicode解码器。
超长字符。ASCII字符可以直接映射到Unicode编码空间中,表示成单个字符。但是,多数的ASCII字符以可以表示成2到6个字符。这样可以欺骗解码器使之误认为这个字符是其他的字符(从而躲过安全检查)。
字节范围检查
你可以强制要求HTTP请求中只包含某个特定字节范围内的字节。这对防止栈溢出攻击是有用的(因为他们通常包含一些“随机”的二进制内容)。
可以用下列指示,限制字节范围从32到126(包含这两个边界值):
SecFilterForceByteRange 32 126
缺省的范围值是0到255,也就是所有的字节值都是被允许的。
当使用multipart/form-data编码(上传文件)的时候,这个指示不检查POST有效载荷中的字节范围。否则会阻止二进制文件的上传。但是当参数被从这样的请求中提取出来的时候,会被检查是否在合法的范围内。
允许其他人看到ModSecurity
通常攻击者无法分辨出是否web server在运行mod_security。你可以通过发送特殊信息或者使用不寻常的HTTP代码(比如406)来出卖你自己。如果希望保持隐藏状态,那么最好是发送返回码500,意思是“Internal Server Error”。收到这个返回值的攻击者通常会认为你的应用程序已经垮掉了。因为脆弱的应用程序在遇到意料外的输入的时候经常会垮掉,ModSecutiry仍然激活这件事情对于攻击者来说仍然是不可见的。
在这个问题上有另外一派人认为,你不应该隐藏你在使用ModeSecurity的事实。理论是如果攻击者看到这个的话,会了解你已经下了功夫,攻击会变得非常困难。这样他们就会离开去寻找更脆弱些的目标。或者可能他们会觉得更有挑战性,从而更坚定的攻击。
缺省情况下Apache会对每个请求返回自身的信息。ModSecurity会保持沉默(这是推荐的状态)。但是你可以通过加上下面这行来让其他人看到ModeSecurity:
SecServerResponseToken On
结果会大概是这个样子:
[ivanr@wkx conf]$ telnet 0 8080
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.
GET / HTTP/1.0
HTTP/1.1 406 Not Acceptable
Date: Mon, 19 May 2003 18:13:51 GMT
Server: Apache/2.0.45 (Unix) mod_security/1.5
Content-Length: 351
Connection: close
Content-Type: text/html; charset=iso-8859-1
Not Acceptable
An appropriate representation of the requested resource /
could not be found on this server.
Apache/2.0.45 (Unix) mod_security/1.4.2 Server at
wkx.dyndns.org Port 80
Connection closed by foreign host.
你应该注意Apache本身支持两个运行时指示:ServerTokens和ServerSignature。使用这些指示你可以彻底隐藏你的服务器的消息,无论ModSecurity是如何配置的。
调试
使用指示SecFilterDebugLog可以选择一个存储调试信息的文件。如果参数不是以“/”开头,Apache的home路径会添加在参数的前面。
SecFilterDebugLog logs/modsec_debug_log
你可以用SecFilterDebugLevel控制调试信息细致到何种程度:
SecFilterDebugLevel 4
可能的日志控制级别包括:
0 - 没有信息
1 - 重大事件(在error_log中也会记录)
2 - 普通信息
3 - 更详细的信息
ModSecurity内部使用调试信息级别最高到9,但是只用于ModSecurity开发者调试用。
请求过滤
当过滤引擎被激活的情况下,每个进入的请求在被处理前都要被解释和分析。分析会以一系列事先设计用来校验请求格式的内置检查作为开始。这些检查可以通过配置指示来控制。在第二个阶段,请求会通过一系列的和这个请求相匹配的用户定义的过滤器。每当发生一个肯定的匹配,特定的动作会被执行。
简单过滤
最简单的规律形式是“简单”形式。看上去是这样的:
SecFilter KEYWORD
象这样的每一个简单过滤器,ModSecurity会在请求中查找关键字。搜索范围很松,会应用在请求的第一行上(象这个样子GET /index.php?parameter=value HTTP/1.0)。对POST请求来说,请求体也会被搜索(当让是在请求体缓存被激活的前提下)。
路径标准化
过滤器不是作用在原始的请求数据上的,而是在一个标准化了的副本上。这样做是因为攻击者可以(而且正在)通过使用不同的躲避技术来逃过监测。比如,你可能希望通过创建一个过滤器来监测shell命令的执行
SecFilter /bin/sh
但是攻击者可以使用一个字符串:/bin/./sh(具有相同的含义)来逃过过滤器。
ModSecurity自动采用下列转换:
l 只对Windows平台生效,/转换成/
l 把/./缩减为/
l 把//缩减为/
l 解码使用URL编码过的字符
你可以选择激活或禁止下列检查:
l 检验URL编码
l 只允许使用指定范围内的字节
在ModeSecurity当前版本中实现的标准化有时候会影响你的正常工作。你可能在写一个在其他地方检查URI的信号的时候遇到很大困难。这是因为URI在请求中的形式是“http://” ,而这个字符串会在标准化过程中翻译成“http:/”。注意在后面这个版本中只有一个斜线。
防止空字节攻击
空字节攻击会迷惑C/C++开发的程序,是它们误认为一个字符串在实际的结束位置之前就结束。这种类型的攻击通常会被合理设置的SecFilterByteRange过滤器拒绝掉。但是如果你没有这样做,空字节会干扰ModSecurity的处理。为了击败这类攻击,ModSecurity在解码阶段搜索空字节并把他们转换成空格。因此,在以前的版本这个过滤器
SecFilter hidden
不会检测到下列请求中的单词hidden
GET /one/two/three?p=visible%00hidden HTTP/1.0
但是在现在的版本是可以检测到的。
正则表达式
我们前面讨论的最简单的过滤器实际上要稍微复杂一点。它的完整的语法是这样的:
SecFilter KEYWORD [ACTIONS]
首先,KEYWORD不是一个普通单词,而是一个正则表达式。正则表达式是设计用来在文本中匹配模式的迷你编程语言。为了充分理解这个强大的工具,需要先充分理解正则表达式。我推荐从下面的资源之一入手:
l Perl兼容的正则表达式的手册页:http://www.pcre.org/pcre.txt
l Perl正则表达式: http://www.perldoc.com/perl5.6/pod/perlre.html
l 精通正则表达式:http://www.oreilly.com/catalog/regex
l Google搜索“正则表达式”:http://www.google.com/search?q=regular%20expressions
要小心(A|B)+类型的正则表达式,在海量的文本上使用这样的表达式会在栈尺寸比较小的平台,比如Windows上导致栈溢出。栈溢出会导致无法不可回复的段错误。
第二个参数是动作列表的定义,用来指定当过滤器匹配成功是发生的动作。关于动作会在后面解释。
反转表达式
如果一个正则表达式的第一个字符是惊叹号,过滤器会反转这个表达式。比如下面的例子:
SecFilter !php
会拒绝所有的不包含单词php的请求。
高级过滤
所以SecFilter可以让你快速上手,但是你很快会发现它的搜索面太宽,工作的不是很好。另一个指示:
SecFilterSelective LOCATION KEYWORD [ACTIONS]
让你可以准确的选择在哪里进行搜索。
KEYWORD和ACTIONS设置和SedFilter是一样的。LOCATION需要解释一下。LOCATION参数包含用管道符分开的一系列的位置标识符。看一下下边的例子:
SecFilterSelective "REMOTE_ADDR|REMOTE_HOST" KEYWORD
只在客户端的IP地址和主机名上使用正则表达式。可能的位置标识符包括所有的CGI变量和其他的一些内容。下面是完整的列表:
l REMOTE_ADDR
l REMOTE_HOST
l REMOTE_USER
l REMOTE_IDENT
l REQUEST_METHOD
l SCRIPT_FILENAME
l PATH_INFO
l QUERY_STRING
l AUTH_TYPE
l DOCUMENT_ROOT
l SERVER_ADMIN
l SERVER_NAME
l SERVER_ADDR
l SERVER_PORT
l SERVER_PROTOCOL
l SERVER_SOFTWARE
l TIME_YEAR
l TIME_MON
l TIME_DAY
l TIME_HOUR
l TIME_MIN
l TIME_SEC
l TIME_WDAY
l TIME
l API_VERSION
l THE_REQUEST
l REQUEST_URI
l REQUEST_FILENAME
l IS_SUBREQ
还有一些特殊的位置:
POST_PAYLOAD – filter the body of the POST request
ARGS - filter arguments, the same as QUERY_STRING|POST_PAYLOAD
ARGS_NAMES – variable/parameter names only
ARGS_VALUES – variable/parameter values only
COOKIES_NAMES - cookie names only
COOKIES_VALUES - cookie values only
甚至还有更特殊的:
HTTP_header – search request header header
ENV_variable – search environment variable variable
ARG_variable – search request variable/parameter variable
COOKIE_name - search cookie with name name
参数过滤的特殊情况
位置标识符ARG_variable在和ARG位置合并使用的时候支持反转。例如:
SecFilterSelective "ARGS|!ARG_param" KEYWORD
会搜索除了名字是“param”的参数之外的所有的参数。
。
Cookies
ModSecurity 对Cookies提供完全支持。默认情况下,版本 0 的Cookies被使用 (Netscape 类型的cookies, Netscape-style cookies)。然而,ModSecurity 同时也支持版本 1 的Cookies(RFC 2965 中定义的Cookies). 你可以使用以下的格式,定义支持版本 1 的cookies:
# enable version 1 (RFC 2965) cookies
SecFilterCookieFormat 1
默认情况下,ModSecurity不会去尝试标准化cookie的名称及值。 然而,一些应用程序或者平台(例如:PHP)会对cookeie编码,以便你可以选择为cookie添加标准化技术。你可以通过对SecFilterNormalizeCookies指令的定义实现:
SecFilterNormalizeCookies On
在ModSesurity 1.8.7版本以前支持SecFilterCheckCookieFormat指令。在1.8.7以后的新版本中这条指令已经被取消。这条指令可以仍然用在配置文件中,但是不起任何作用。在1.9.X以后的版本中这条指令已经被完全取消。
输出过滤(Output filtering)
MoSecurity 在Apache 2版本中支持输出过滤。默认情况下,输出过滤是被禁止的,如果你想要使用必需首先打开这个选项:
SecFilterScanOutput On
之后,使用特殊变量OUTPUT简单添加选择过滤器:
SecFilterSelective OUTPUT "credit card numbers"
在http://www.webkreator.com/php/许多和我一起研究这些朋友知道我对防止PHP致命错误( fatal errors)有些无能为力。我花了很长时间去研究防止PHP的致命错误信息泄漏给用户。 (×××)(参考:http://www.webkreator.com/php/co ... d-parse-errors.html)
但是现在,最终在这方面我不用太担心了。以下的指令可以从返回信息(response)的主体文件中捕获PHP输出错误,而不是从单独的错误回应(response)中捕获,并且执行定制的PHP脚本(同时通报应用程序管理员)。
SecFilterSelective OUTPUT "Fatal error:" deny,status:500
ErrorDocument 500 /php-fatal-error.html
你应该注意到尽管你可以混合输入输出过滤器,但是它们不能在同一时间执行。输入过滤器在一个请求被Apache处理之前被执行。输出过滤器在Apache完成请求处理以后被执行。
动作(Actions)skipnext 和 chain不能在输出(output)过滤器工作。输出过滤仅仅用于纯文本和HTML输出的过滤。添加常规的二进制内容的表达式(例如:Image)将仅仅会使服务器慢下来(~~~~~~).ModSecurity 能基于它的mime类型有选择的添加输出过滤给响应(responses)。使用SecFilterOutputMimeTypes指令你能告诉它哪一个mime 类型去监视:
SecFilterOutputMimeTypes "(null) text/html text/plain"
上面的一个简单ModScurity的配置实例会给纯文本文件、HTML文件,、和mime类型不是被特殊的"(null)"位置的文件添加输出过滤。使用输出缓冲将使ModSecurity 保持完整的内存中的页输出,无论它本身有多大。内存开销是页长度的2倍以上。
动作(Actions)
有以下几种动作:
主动作(action)将生成一个决策决定是否去继续请求或者拒绝请求。有且只有一个主动作存在。如果你在parameter里设置了几个主动作,最后一个动作将被执行。主动作为deny,
pass, 和 redirect(转向).
第二动作将由主动作在决策中作定义,并在一个独立匹配的过滤器(filter)中被执行。在第二动作中可以是任何值,例如:exec 是一个第二动作。
下面的流动作能改变相应的规则的流向,因为过滤引擎能跳到其他规则,或者跳到一个或几个规则。实现动作是chain 和 skip.
参数不是真正的动作,而是一个针对过滤器的附加参数的方法(method)。有些参数能被用于真正的动作。例如:status 给主动作deny提供一个响应编码。
指定动作(Specifying actions)
你可以把动作放在三个地方。一个是SecFilterDefaultAction指令,在这里你可以定义你想在大多数过滤匹配中被执行的动作:
SecFilterDefaultAction "deny,log,status:500"
这个例子定义了一个由三个动作组成的动作列表。逗号用与在列表中分开动作。开始的两个动作是由单个的单词组成。但是第三个动作需要一个参数,用冒号把参数和动作名分隔开。
你也能指定过滤器预处理动作。做为一个可选参数,有两个过滤器指令可以接受一个指定动作的设置(SecFilter 和SecFilterSelective)。当使用的过滤器预处理动作是一个伪装请求时,这个请求在过滤匹配器中将会被拒绝。如果你想容许请求继续,你必须明确的设置一个non-fatal动作(例如:“log,pass”.)
对于1.8.6,如果你指定了non-fatal为默认动作(例如:“log,pass”.),那么在mod_security初始化的阶段它就会被忽略。初始化阶段仅仅用来收集关于请求的信息,容许non-fatal动作是因为一些请求块错误(在mod_security中对于内部处理)。因此,如果你想mod_security在探测"detect-only"模式下运行,你应该禁止所有固有确认(检查 URL encoding, Unicode, cookie 格式化, byterange).
内置动作(Built-in actions)
pass
容许在过滤匹配中请求被继续。这个动作用在当你想纪录一个匹配(match)而不并不想执行其他的动作时候。
SecFilter KEYWORD "log,pass"
allow
在这个动作执行后,请求将被容许通过,并且没有别的过滤器被重试。
# stop filter processing for request coming from
# the administrator's workstation
SecFilterSelective REMOTE_ADDR "^192.168.2.99$" allow
deny
在过滤匹配中中断一个请求处理。除非status动作也在使用。ModSecurity 会立即返回一个HTTP 500错误代码。如果一个请求被拒绝,文件头mod_security-action将会被添加到请求文件头列表中去。这个文件头包括code使用状态。
Status
当一个请求被拒绝的时候使用替代HTTP状态代码。
下面的规则:
SecFilter KEYWORD "deny,status:404"
当他被触发的时候将返回"Page not found"信息。如果在配置里有这条规则Apache 错误提示信息会被触发。所以,如果你以前已经为一个设定的状态定义了一个定制的错误页,那么它将会被执行并且给用户显示。
Redirect
在过滤匹配中可以重定向用户到指定的URL.例如:
SecFilter KEYWORD "redirect:http://www.modsecurity.org"
这个配置指令不考虑HTTP状态代码或者deny关键字。注意,URL中不能包括逗号。
Exec
在过滤匹配中执行二进制文件,需要在指令中添加要执行的文件的完整路径,例如:
SecFilter KEYWORD "exec:/home/ivanr/report-attack.pl"
如果这条指令存在,它对主动作不产生影响。这个动作总是调用不带参数的脚本,但是提供所有在环境中的信息。所有的通用的CGI环境变量都将放在这里。你可以在预过滤匹配中执行一个二进制文件。完成以后将增加一个mod_security-executed的报头到请求包列表中。你应该理解调用线程会导致在所有的线程将会复制到新的线程。在多进程选项中调用会导致更大的开销。
log
日志过滤用于纪录Apache的错误日志。
nolog
不纪录Apache的错误日志。
skipnext
这个动作容许你跳过一个或者多条规则。当你设定在特殊情况下,不需要完成一些校验,你可以用这个动作。默认情况下,这个动作会跳过下一条规则。如果你指定了可选参数,它能跳过任何规则的数目。
SecFilterSelective ARG_p value1 skipnext:2
SecFilterSelective ARG_p value2
SecFilterSelective ARG_p value3
Chain
链接规则容许你将几条规则链接到到一起。只有在链接中的最后一条规则会影响请求,在它前面的所有的规则也必须被匹配。
在这里举一个例子:
我想限定管理员用户只能从指定的IP地址登陆。但是,管理员登陆界面是和别的用户共享的,并且我不能用标准的Apache界面。因此,我用了这两条规则:
SecFilterSelective ARG_username admin chain
SecFilterSelective REMOTE_ADDR "!^YOUR_IP_ADDRESS_HERE$"
如果参数username存在并且它的值是admin那么第一条规则匹配。之后第二条规则被执行,并且它会尝试用远程请求地址和单独的IP地址匹配。如果请求地址不匹配(注意:以!做为开始),则请求被决绝。
pause
在响应请求之前可以暂停几毫秒。这对于减速或者完全拒绝一些web扫描是非常有用的。一些扫描软件如果暂停过长它就直接放弃扫描。
在一种情况使用这个选项要特别的小心。每一个web服务器的安装配置是限定的,在任何时候它都需要提供最大请求数。如果弱扫描软件是并行执行请求,使用这个选项有一个较长延迟时间,可以创建一个“voluntary”的拒绝服务攻击。
mod_security增加的请求报头(Request Header)
只要有可能,ModSecurity会在请求报头中增加信息,从而容许你的脚本发现并使用它。显然,为了你的脚本能够被执行,你必须配置ModSecurity避免它拒绝请求。乍看起来,可能有点奇怪我使用请求报头,而不是其他的手段,比如环境变量,来达到这个目的。虽然使用环境变量看起来更规范一些,输入报头对于使用ErrorDocument指示(见下文)来执行的脚本来说总是可见的,凡是对于环境变量则不然。
这是添加的报头的列表:
a) mod_security-executed; 被执行的二进制文件的路径
b) mod_security-action; 返回的状态码
c) mod_security-message; 监测到的错误信息,和记录在error_log中的信息相同。
使用ErrorDocument来处理规则匹配
如果你的配置返回了HTTP状态码500,而且你配置Apache使其是要在这个状态出现时都执行一个自定义的脚本(比如ErrorDocument 500 / error500.php)来使你能够使用自己喜欢的脚本引擎来相应这些错误。关于错误的信息会放在环境变量REDIRECT_*和HTTPD_MOD_SECURITY_*里(正如这里描述的:http://httpd.apache.org/docs-2.0/customerror.
html)。
让ModSecurity和你的防火墙交流
某些情况下,检测到一个显著的危险攻击或是一系列攻击后,你会希望组织同一个来源的进一步的攻击。你可以通过修改防火墙使其拒绝从某一特定的IP地址发出的全部流量来做到这一点(我在iptables的基础上写了一个助手脚本,可以在这里下载:http://www.apachesecurity.net)。
这个方法可能非常危险因为它会导致拒绝服务(DoS)攻击。比如,一个攻击者可以使用一个代理来发起攻击。拒绝来自一个代理服务器的所有请求是很危险的事,因为所有合法的用户也会收到影响。
因为多数代理会发送描述原始客户端的信息(可以在下面的网址找到有关的信息:http://www.webkreator.com/cms/view.php/1685.html,在“Stop Hijacking”一节),我们可以试着聪明一点,找到真正的IP地址。虽然这样能工作,但是考虑下面的情况:
l 攻击者在直接访问应用程序,但是伪装成一个代理服务器,引用一个随机的(或者合法的)IP地址作为“真实的”源IP地址。如果我们基于推断出的信息开始拒绝请求,攻击者会简单的替换IP地址然后继续攻击。结果是我们禁止了合法的用户,但是攻击者仍然在自由地寻找应用程序地漏洞。
所以只有在下列情况下有用:你不允许通过代理访问你的应用程序,或者只允许通过广为人知的,更重要的,可信任的代理访问。
如果你仍然希望基于IP地址来禁止请求(不理会我们所有的警告),你需要写一个小的脚本,在过滤器匹配的时候执行。这个脚本应该从环境变量里取出攻击者的IP地址,然后调用iptables或者ipchains来禁止这些IP地址。在mod_security以后的版本中我们将会包含一个这样的脚本示例。
文件上传支持
ModSecurity支持multipart/form-data编码用于文件上传
选择上传文件到哪里
ModSecurity总是上传文件到临时目录。你可以用SecUploadDir指示选择目录:
SecUploadDir /tmp
最好选择一个私有文件夹存放文件,只允许启动web服务器的用户访问。否则,其他的服务器用户可能访问通过web服务器上传的文件。
校验文件
你可以选择执行一个外部脚本在允许文件通过web服务器到达应用程序之前校验这个文件。SecUploadApproveScript指示提供了这个功能。如下例所示:
SecUploadApproveScript /full/path/to/the/script.sh
一个命令行参数会提供给脚本——正在被上传的文件的完整路径。脚本可以对文件作任何操作。处理完之后,响应结果会输出到标准输出。如果相应结果的第一个字符是“1”,文件将会被接受。如果是其他的结果,(上传文件的)请求将会被拒绝。你的脚本可以用响应结果来提供描述性更强的错误信息。这个信息会被输出到debug log。
存储上传的文件
你可以选择保存通过web服务器上传的文件。只要在你的配置中添加下列行就可以了:
SecUploadKeepFiles On
文件会被存放在SecUploadDir指示指定的目录中。
上传内存限制
Apache 1.x没有提供一个合适的底层架构用来作请求侦听。除非把请求整个放在内存中才能侦听。Apache 1.x提供一个选择,分析内存中的multipart/form-data(文件上传)请求,或者根本不分析(选择性的关闭POST处理)。
但是,使用Apache 2.x,你可以定义用来解析内存中存放的multipart/form-data的内存数量。当一个请求大于你允许的数量的时候,会使用一个临时文件。缺省值是60KB,但是可以通过SecUploadInMemoryLimit指示来改变:
SecUploadInMemoryLimit 125000
阻抗不匹配
很多web应用程序防火墙有一个困难的工作——在对应用程序和商业逻辑完全不了解的情况下,搞清经过的数据的意思。他们提供的保护来源于在外部拥有的一个独立安全层。因为数据确认作了两次,可以在不触动应用程序的前提下增加安全性。但是,在某些情况下,每件事情都作两次会带来问题。在通信协议没有很好定义的地方,或者在设备或应用程序在做一些规范中没有定义的事情。
最糟糕的违规者是cookie规范。(实际上是所有这4个定义:http://wp.netscape.com/newsref/std/cookie_spec.html, http://www.ietf.org/rfc/rfc2109.txt,
http://www.ietf.org/rfc/rfc2964.txt,http://www.ietf.org/rfc/rfc2965.txt)。因为很多真实的生活可能发生的情况,在这个规范中没有定义——留给程序员去做任何他们认为适宜的事情。大多数情况这不是问题,如果cookie是结构良好的话——事实上多数情况下是的。问题不明显还因为多数应用程序解析的cookie都是这些应用程序自己发送的。如果你从web应用程序防火墙的角度观察,当一个确定的对手试图突破它的时候,这就是问题了。
我会用一个例子来解释。
ModSecurity的1.8.x分支,直至1.8.6(我在1.8.7中做了改进)使用了一个cookie解析器。当我写这个解析器的时候,我觉得它真的很好,因为它能够处理v0和v1的cookie。但是,我犯了一个错误,没有象一个攻击者那样去思考。正如Stefan Esser向我指出的,在v0和v2之间的格式差异可能被利用,使得一个v1的解析器看到一个cookie,但是一个v0的解析器看到更多。就像这样:
Cookie: innocent=”; nasty=payload; third=”
V0的解析器不识别双引号。它只寻找分号然后分割报头。一个这样的解析器看到的多个cookie:“innocent”,“nasty”,“third”。另一方面,V1的解析器只看到一个cookie——“innocent”。
阻抗不匹配是如何影响web应用程序防火墙的用户和开发者的呢?它当然会让生活变得复杂,但是这没关系——这是游戏的一部分。开发者必须合并比较好和比较快的解析程序。例如,ModSecurity 1.8.7包含两个cookie解析器。用户可以选择任一使用(默认使用v0的解析器)。但是因为不能自动化,这样的改进只是使防火墙更加复杂——又多了一件需要用户思考和配置的东西。
另一个方面,如果不想考虑cookie解析器的问题,用户总可以后退回去使用HTTP中那些定义的更好的部分。例如,用户可以使用HTTP_Cookie来定位整个cookie报头,而不是用Cookie_innocent来定位一个单独的cookie。其他变量,比如ARGS,可以看到全部的变量,不管对手多么努力的掩饰他们。
其他特性
隐藏服务器标识
一个常用的减缓和迷惑攻击者的技术就是改变web服务器的标识。Web服务器通常会在每个HTTP响应的Server报头中包含服务器的标识。Apache在这个方面更加明显,缺省情况下不只发送完整的名字和版本号,而且还允许服务器模块把它们的版本也附加上。
为了改变Apache web服务器的标识,你可能不得不查看源码,会发现“Apache”这个名字是硬编码的,然后改变它,重新 |