modsecurity配置指令学习
事务(transactions)
Console(控制台)
1 Introduction
Modsecurity是保护网络应用安全的工作。不,从零开始。我常称modsecurity为WAF(网络应用防火墙),这是种被广泛接受的叫法,它指的是为保护网络应用而专门设计的产品族。也有些时候我称它为HTTP入侵检测工具,我认为这个称呼更好的描述了modsecurity做了什么。
Understanding ModSecurity
像Apache为其他模块所做的一样,Apache为modsecurity处理一些基础任务:
1、 加密解密
2、 破坏HTTP请求的入站连接流
3、 部分性解析HTTP请求
4、 引导modsecurity,选择正确的配置文本(<VirtualHost>,<Location>等)
5、 De-chunks必需的请求体
反向代理模式时Apache会执行几个别的任务:
1、 请求转发到后端服务器(SSL或者非SSL)
2、 部分性解析HTTP响应
3、 De-chunks必需的响应体
What ModSecurity Does
Modsecurity提供的功能大概能分成四个部分:
Parsing解析:
Modsecurity会努力解析尽可能多的数据。Security-conscientious解析器会提取储存数据,义工在规则中使用,并支持一定的数据格式。
Buffering缓存
典型安装时,请求体和响应体都会缓存。这就意味着,modsecurity在请求被传到应用服务器进行处理之前,就见到完整的请求了。在响应被送到客户端之前就见到了响应。缓存是一个重要的特性,因为只有这种方式才能可靠的拦截数据。缓存也存在缺陷,他需要额外的RAM来存储请求体和响应体数据。
Logging日志
全事务日志(又称审计日志)占据了modsecurity所做工作的很大一部分。你可以利用日志记录完整的HTTP流量,而不是仅仅粗略的访问日志信息。请求头、请求体、响应头、响应体,所有这些信息你都能获得。只有日志有这个功能
What Rules Look Like规则是什么样子的
ModSecurity围绕两种东西:配置和规则。配置告诉modsecurity怎么处理它遇到的数据。规则决定对要处理的数据做什么。尽管现在看规则是怎么运作的还太早,我将给你展示一个快速的例子,仅仅告诉你规则是什么样子的:
SecRule ARGS “<script>” log,deny,status:404
即使没有进一步的帮助,你大概也能看出来规则指定了在输入数据(<script>)中我们希望得到什么样的数据。类似的,你很容易发现当得到期望模式(log,deny,status:404)时会发生什么。如果我告诉你规则的一般语法,你将会更加清晰,例如下面:
SecRule VARIABLES OPERATOR ACTIONS
三部分的含义如下:
VARIABLES告诉ModSecurity上哪查找,例子中的ARGS变量,表示所有的请求参数;。
OPERATOR告诉ModSecurity怎么查找,例子中,我们用一个正则表达式模式,他将和ARGS匹配。
ACTIONS告诉ModSecurity,当匹配发生时,将会做什么。例子中的规则给出了指示:记录问题,拒绝交互,用状态号:404拒绝。
我希望你不要对第一条规则的简单而失望,我向你保证通过组合ModSecurity提供的不同的工具,你能够写出有用的规则来实现负责的逻辑功能。
Transaction Lifecycle交互周期
ModSecurity中,每次交互都需要五步或五段:每一段,modSecurity都要在开始做一些工作(例如:剖析数据),激发这一段中指定的规则,让他起作用,或者段规则结束之后做一两件事情。乍一看,五步很多,但是每一段的存在都有一个原因。总有一件或者几件事情只能在交互周期的某一特定时刻发生。
请求头(1)
请求头段是modsecurity第一个切入点。这一段的首要目的是允许规则作者在代价很高的请求体处理过程发生之前对请求进行评估。请求头段会影响modsecurity怎么处理一个请求体。例如,modsecurity不会默认分析XML请求体,但是你可以通过在第一阶段指定合适的规则来指示他这么做。
请求体(2)
请求体阶段是主要的请求分析阶段并且当接收到一个完整的请求体并进行处理时,这一阶段立即发生。这一阶段的规则可以任意处理所有的请求数据。
响应头(3)
响应头阶段在接收到响应头之后,还没有读取响应体之前发生。这一阶段的规则将会决定是否检查响应体。
响应体(4)
响应体阶段是主要的响应分析阶段。这一阶段一开始,就会读取响应体的数据以供规则使用。
记录(5)
记录阶段很特殊,首先,这是唯一的一个你不能锁定的阶段。交互完成之后,这个阶段才开始运行,所以你什么都不能做,只能记录发生的事实。这个阶段的规则将会控制怎么记录。
周期实例
为了让你更好的理解每个交互阶段发生了什么,我们将研究一个POST交互的详细调试日志。因为下面这个交互将会运用modsecurity的大多数部分,我们特意选择了一个使用请求体来发送数据的交互类型。为了使事情相对简单,我使用了一个没有任何规则的配置,为了清晰起见,去除了一些调试记录行、时间戳和一些附加的元数据。
注意:不要期望在此就能理解关于日志的所有事情。只是有一个关于modsecurity如何工作的大体感觉。开始使用modsecurity之后,你很快就会发现调试记录是一个不可缺少的书写规则和疑难排解的工具。
我在这一段文章中使用的交互很直接。我把请求数据放在两个不同的地方,参数a放在查询字符串中,参数b放在请求体中,但是在这个请求当中再没有值得注意的地方了。
POST /?a=test HTTP/1.0
Content-type: application/x-www-form-urlencoded
Content-Length:6
B=test
响应一点都不起眼:
HTTP/1.1 200 OK
Date:Sun,17 Jan 2010 00:13:44 GMT
Server:Apache
Content-Length:12
Connection:close
Content-Type:text/html
Hello World!
请求头available之后但是请求体(如果有的话)未读之前,Apache第一次启用ModSecurity。先出现初始化消息,包含了mod_unique_id产生的独立的交互ID号。使用这个信息你应该能够把调试日志里的信息和你访问的信息以及审计日志里的信息配对。这时,modsecurity将解析请求行和请求头上的信息。在这个例子中,查询字符串包含了一个简单的参数a,所以你会看见记录它的发现的消息。然后Modsecurity会创建一个交互语境,并引发REQUEST_HEADERS段:
[4]初始化交互(txid SopXW38EAAE9YbLQ)
[5]增加请求参数(查询字符串QUERY_STRING):名字“a“,值“test”
[4]创建交互语境(dcfg 8121800)
[4]开始段REQUEST_HEADERS
如果一个规则没有锁定交互,那么现在modsecurity就会给Apache返回控制,以允许其他模块在控制返回给他之前处理请求。在第二阶段,modsecurity先读取然后处理请求体,前提是请求体存在。在接下来的例子中,你能看到输入过滤器中的三个消息,告诉你读取了什么。第四条消息告诉你,从请求体中获取了一个参数。请求(application/x-www-form-urlcoded)中使用的内容类型是modsecurity能识别并且自动分析的类型。一旦处理了请求体,就会处理ERQUEST_BODY规则。
[4]第二阶段开始(dcfg 8121800)
[4]输入过滤器:正在读取请求体
[9]输入过滤器:斗式HEAP包含6个字节
[9]输入过滤器:斗式EOS包含0个字节
[5]正在增加请求参数(BODY):名称“b”,值:“test”
[4]输入过滤器:已完成接受请求体(长度6)
[4]开始阶段REQUEST_BODY
记录当中一直提到的过滤器是modsecurity处理请求体和响应体的部分。
[4]钩住嵌入过滤器:增加输入转发过滤器(r 81d0588)
[4]钩住嵌入过滤器:增加输出过滤器(r 81d0588)
Modsecurity没法送一大块数据给请求处理程序,就会在调试日志里面增加一条消息,最后一条小时用来说明缓冲区中没有数据了。
[4]输入过滤器:转发输入:mode=0,block=0,nbytes=8192(f 81d2228,r 81d0588)
[4]输入过滤器:转发了6个字节
[4]输入过滤器:发送了EOS
[4]输入过滤器:输入转发完成
不久之后,输出过滤器将会开始接收数据,就在此时引发RESPONSE_HEADERS规则:
[9]输出过滤器:接收输出(f 81d2258,r 81d0588)
[4]开始RESPONSE_HEADERS阶段
一旦所有的规则都运行过了,modsecurity将继续在缓存区中储存响应体,之后运行RESPONSE_BODY规则。
[9]输出过滤器:斗式MMAP包含12个字节
[9]输出过滤器:斗式EOS包含0个字节
[4]输出过滤器:完成接收响应体(缓冲区满-12个字节)
[4]开始阶段RESPONSE_BODY
再一次假设没有锁定规则,积累的响应体将会转发给客户端。
[4]输出过滤器:输出转发完成
最后,记录阶段开始。先运行LOGGING规则来影响记录动作,这之后如果有必要的话才会启动审计记录子系统来记录交互。审计记录子系统发的消息将会是日志中最后一条交互消息。在这个例子中,modsecurity告诉我们他没有发现交互当中任何值得关注的事情并且没有理由记录:
[4]开始记录
[4]开始LOGGING阶段
[4]审计记录:忽略了一个不想管的请求。
处理阶段:
ModSecurity 2.x允许把规则至于下述五个阶段之一:
请求头(REQUEST_HEADERS)
请求体(REQUEST_BODY)
响应头(RESPONSE_HEADERS)
响应体(RESPONSE_BODY)
记录(LOGGING)
为了在规则执行时选择阶段,需要使用阶段命令,可以通过规则中直接使用,也可以通过SecDefaultAction指令。
SecDefaultAction “log,pass,phase:2”
SecRule REQUEST_HEADER:Host “!^$””deny,phase:1”
注意:要注意规则的执行时依赖于阶段,即使是一个配置文件中的两条邻近的规则,只要是设置了在不同的阶段中执行,他们就不会是一个接一个的生效。配置文件中的规则顺序仅仅是在规则各自的阶段中是重要的。在使用Skip和SkipAfter动作时尤为重要。
注意:LOGGING阶段比较特别,无论前面的各个阶段发生了什么事,都会每个事务的最后被执行。这就意味着哪怕是请求被中断或是放行事务时都会被执行。
请求头阶段:
这个阶段的规则会在apache完成请求头的读取后立即被执行(post-read-request阶段),这时,还没有读取请求体,意味着不是所有的参数都可用。如果你必须让规则尽早运行,应把规则放在这个阶段(在apache使用这个请求做某些事前),在请求体被读取前做些事情,从而决定是否缓存这个请求体,或者决定你将希望这个请求体如何被处理(如是否以XML格式解析或不解析)。
注意这个阶段的规则无法影响apache的范围指令(Directory,Location,LocationMatch等)像post-read-request钩子一样还无法得到信息。VirtualHost指令有些例外,如果想在apache的locations使用ModSecurity规则,那么他们应该运行在阶段2,参考apache请求环/ModSecurity处理阶段图标。
请求体阶段:
这是通用输入分析阶段,大部分传统的应用规则不在这儿,这个阶段你肯定能收到参数(只有读取过请求体后),在请求体阶段,ModSecurity支持三种编码类型。
Application/x-www-form-urlencoded – used to transfer from data
Multipart/from-data – used for file transfers
Text/xml – used for passing XML data
大部分WEB应用还没有使用其他的编码方法。
响应头阶段:
发生在响应头被发送到客户端之前,如果你想观察响应发生前就在这儿运行,如果你想使用响应头来决定你是否想缓存响应体也行。注意一些响应状态码(如404)在请求环的早期就被apache管理着,我也无法触发预期。加上apache在后面的钩子上双增加了一些响应头(如日期、服务器和连接信息等),这些我们无法触发和审查。在代理配置模式下或使用phase:5(logging)工作的较好。
响应体阶段:
这是通用输出分析阶段,这里你能运行规则截断响应体(当然提供缓存)。这个阶段你想检查输出的HTML信息公布、错误信息和失败的验证文字。
日志阶段:
在日志发生前运行的一个阶段,放在这个阶段的规则只能影响日志记录器如何执行,这个阶段可以检测apache记录的错误信息,在这个阶段你不能拒绝或阻断连接,因为太迟了,这个阶段也允许检测其他的响应头,如那在phase:3或者phase:4阶段中不可用的。注意在这个阶段,你应当小心不要继承破坏性的动作到规则中,这样的情况在ModSecurity2.5.0及其以后的版本中被当做配置错误。
Embedded vs. Reverse Proxy Mode
嵌入式与反向代理模式
Modsecurity并不关心自己是否处于嵌入式或反向代理模式,反向代理模式时,Apache负责向后端服务器转发数据并接收发回来的数据,所以modsecurity不用关心。只有一点小区别,下面我列出来供参考:
1、 嵌入式时,通常会使用一个资源(一个script脚本或者一个file文件)来满足每一个请求。Modsecurity规则会检查这些文件(SCRIPT_*允许访问的变量族)的属性。反向代理模式时,实际上是由后端服务器来满足所有的请求。也就是说不使用本地资源,并且相关变量的使用一点意义也没有。
2、 嵌入式时,
Integrating with ClamAV
结合clamav
Clamav是一个开源防病毒软件,如果你已经安装了Clamav,你可以使用下面的脚本扫描modsecurity的文件。(Clam AntiVirus是一个类UNIX系统上使用的反病毒软件包。主要应用于邮件服务器,采用多线程后台操作,可以自动升级病毒库。)
3 Configuration
Modsecurity已经编译好并且准备好运行了,现在我们可以对他进行配置。这一段落以及很多分段,会讲到modsecurity配置的每一部分,并明确的配置每一个小细节。
Table 3.1. Main configuration directives
Directive Description
SecArgumentSeparator Sets the application/x-www-form-urlencoded parameter separator
SecCookieFormat Sets the cookie parser version(设置cookie解析器版本)
SecDataDir Sets the folder for persistent storage(设置用于持久性存储的文件夹)
SecRequestBodyAccess Controls request body buffering
SecRequestBodyInMemoryLimit Sets the size of the per-request memory buffer
SecRequestBodyLimit Sets the maximum request body size ModSecurity will accept
SecRequestBodyNoFilesLimit Sets the maximum request body size, excluding uploaded files
SecResponseBodyAccess Controls response body buffering
SecResponseBodyLimit Specifies the response body buffering limit
SecResponseBodyLimitAction Controls what happens once the response body limit is reached
SecResponseBodyMimeType Specifies a list of response body MIME types to inspect
SecResponseBodyMimeTypesClear Clears the list of response body MIME types
SecRuleEngine Controls the operation of the rule engine
SecTmpDir Sets the folder for temporary files
Miscellaneous Options各种各样的选项
这一段落的指令几乎不会用到,但是有了他们,我们可以完全掌握modsecurity的配置选项。你也应该意识到他们的存在,并在一些罕见的需要使用它们的时候会使用它们。
可以使用SecArgumentSeparator指令改变application/x-www-form-urlencoded编码的参数separator。application/x-www-form-urlencoded编码是用来传输所有的GET参数和大部分POST参数的。
SecArgumentSeparator &
实际上,所有的application都使用一个&来达到这个目的,但是也有一些不会。HTML4.01说明书建议,为了方便,application支持使用分号作为separators(参考段落B.2.2URI属性值中的&)。PHP则可以把任何字符党组separator。
SecCookieFormat指令会从modsecurity支持的两个cookie解析器当中选出一个。实际上,所有的applications都使用Netscape-style cookie(有时也当做version 0)所以,几乎没有理由来改变这个设置:
SecCookieFormat 0
4 Logging
这一段落详细的讲述了modsecurity的logging能力。Modsecurity所做的工作中,Logging占了大部分。
Debug Log调试日志
调试日志是你进行疑难排解的最基本的工具,尤其是在你刚开始学习modsecurity怎么工作的时候。
Table 4.1. Debug log directives
Directive Description
SecDebugLog Path to the debug log file
SecDebugLogLevel Debug log level
理论上调试日志有10个等级,但不是全部都使用。1-3等级的消息是有意义的,并且被复制到Apache的error log中。更高等级的消息大部分是用来解决问题和调试的。
Table 4.2. Debug log levels
Debug log level Description
0 No logging
1 Errors (e.g., fatal processing errors, blocked transactions)
2 Warnings (e.g., non-blocking rule matches)
3 Notices (e.g., non-fatal processing errors)
4 Informational
5 Detailed
9 Everything!
你会想把调试日志的等级控制的很低(当你想把所有的消息复制到调试日志时,使用等级3;或者你只想把它们放在error log中时,使用等级0)。这是因为调试日志的消息会超过50条(每一条消息都是一条I/O操作),并且平巨额每个交互至少有7KB的数据。为每一个交互都记录所有的消息将会消耗大量的资源。
一个简单的调试日志行是这样的:
[18/Aug/2009:08:18:08 +0100] [192.168.3.111/sid#80f4e40][rid#81d0588][/index.html]}
[4] Initialising transaction (txid SopVsH8AAAEAAE8-NB4AAAAD)。
这一命令行以元数据开头,而元数据通常比消息本身还要长。
5 Rule Language Overview规则语言概述
Operators
截止到目前,所有的例子都是假设使用正规模式对输入进行匹配。尽管正则表达式非常有用,我们还是经常想做一些其他的事情。这时候就会用到运算符。事实是modsecurity总是使用一个运算符,而不是你在一个规则中指定一个运算符它才使用运算符,不指定的话,它就使用正规模式匹配。所以作为开始,下面的规则明确指定了一个运算符——正规模式正在匹配一个!
SecRule ARGS:username “@rx ^(admin|root)$”
上面的规则检查请求用户名是admin还是root。你也许已经注意到了几件事情:
运算符以@开头
运算符总是被放在第二条SecRule token开头(token貌似指的是引号部分)
运算符后面有一个空格。无论运算符后面是不是一个简单的运算符参数。@rx运算符的参数是一个正则表达式
当规则中带有明确的运算符的时候,你需要在token周围使用双引号,token内部总是有一个空格。没有双引号,Apache将会混淆。
运算符之所以强大在于它提供的广泛的功能。表5.9中列出的字符串操作符,使用最频繁。目前你已经看到了足够的使用正规模式匹配的例子。除了简单的匹配运算符(@beginsWith,@endsWith等)之外,modsecurity还提供了类似的匹配,可以立即匹配大量的模式。@pm@pmFromFile就是这么用的。
String matching operators字符串匹配运算符
字符串匹配运算符从输入提取一个字符串,然后尝试将他和提供的参数进行匹配。@rx和@pm是经常使用的运算符,因为他们的versatility(@rx)和速度(@pm),剩下 运算符也有用,尤其是当你 需要不同种类的扩展的时候,@rx和@pm都不支持。
Table 5.9. String matching operators
Operator Description
@beginsWith Begins with
@contains Contains
@endsWith Ends with
@rx Regular pattern match(正规模式匹配)
@pm Parallel matching(平行匹配)
@pmFromFile (@pmf in v2.6) Parallel matching, with arguments from a file(与文件中的参数进行平行匹配)
@streq String equal to
@within Within
Numerical operators数字运算符
表格5.10,使比较数字值变得很简单(previously you had to resort to使用复杂的正则表达式)
Table 5.10. Numerical operators
Operator Description
@eq Equal
@ge Greater or equal
@gt Greater than
@le Less or equal
@lt Less than
Validation operators
表格5.11,all validate input in some way.,
Table 5.11. Validation operators
Operator Description
@validateByteRange Validates that parameter consists only of allowed byte values
@validateDTD Validates XML payload against a DTD
@validateSchema Validates XML payload against a Schema
@validateUrlEncoding Validates an URL-encoded string
@validateUtf8Encoding Validates an UTF-8 encoded string
Miscellaneous operators
Table 5.12. Miscellaneous operators
Operator Description
@geoLookup Determines the physical location of an IP address
@inspectFile Invokes an external script to inspect a file
@rbl Looks parameter against a RBL (real-time block list)
@verifyCC Checks if the parameter is a valid credit card number
Actions
动作会使modsecurity精简(tick)。
Disruptive actions
表格5.13指定了规则成功匹配时将会做什么。每一条规则都必须和一个disruptive动作结合。Pass动作时唯一例外,当规则匹配时他会继续处理规则。其他所有的动作都会以某一指定方式进行拦截。
Table 5.13. Disruptive actions
Action Description
Allow Stop processing of one or more remaining phases(停止一个或更多的剩下阶段的处理)
Block Indicates that a rule wants to block(规则会拦截)
Deny Block transaction with an error page(用一个错误页面拦截交互)
drop Close network connection(关闭网络连接)
pass Do not block, go to the next rule(不拦截,继续下一条规则)
proxy Proxy request to a backend web server(对后端服务器进行代理请求)
redirect Redirect request to some other web server()
Flow actions
表格5.14中的动作会转变规则在一个段中处理的方式。
Table 5.14. Flow actions
Action Description
chain Connect two or more rules into a single logical rule(把两条或更多的规则在一条简单的逻辑规则里进行连接)
skip Skip over one or more rules that follow(跳过紧接下来的一条或几条规则)
skipAfter Skip to the rule or marker with the provided ID(跳到指定ID号的规则或标志)
Metadata actions
表格5.15中的metadata actions提供了规则的附加信息,把这些信息和error消息结合起来就会更容易理解他们为什么发生的。
Table 5.15. Metadata actions
Action Description
id Assign unique ID to a rule(给规则分配单独的ID号)
phase Phase for a rule to run in(规则在哪一段中运行)
msg Message string(消息字符串)
rev Revision number()
severity Severity
tag Tag
Variable actions变量动作
5.16中的变量动作处理变量,你可以用他们来对变量进行设置、改变和删除。
Table 5.16. Variable actions
Action Description
capture Capture results into one or more variables()
deprecatevar Decrease numerical variable value over time
expirevar Remove variable after a time period(一个时间段之后删除变量)
initcol Create a new persistent collection(创建一个新的连续的集合)
setenv Set or remove an environment variable(设置或删除环境变量)
setvar Set, remove, increment or decrement a variable()
setuid Associate current transaction with an application user ID (username)(用应用用户ID、用户名和当前交互结合起来)
setsid Associate current transaction with an application session ID(用应用会话ID和当前交互结合起来)
Logging actions
5.17的Logging动作会影响日志产生的方式。需要使用ctl动作来整体控制交互记录。
Table 5.17. Logging actions
Action Description
auditlog Log current transaction to audit log(把当前交互记录得到audit log里面)
log Log error message; implies auditlog(记录错误信息,implies auditlog)
logdata Log supplied data as part of error message()
noauditlog Do not log current transaction to audit log(不把当前交互记录到auditlog中)
nolog Do not log error message; implies noauditlog()
sanitiseArg Remove request parameter from audit log(从auditlog中删除请求参数)
sanitiseMatched Remove parameter in which a match occurred from audit log(从audit log中删除匹配参数)
sanitiseRequestHeader Remove request header from audit log(从audit log中删除请求头)
sanitiseResponseHeader Remove response header from audit log(从audit log中删除响应头)
Special actions
5.18的special动作是sort的gateways,使用他们可以访问其他功能类。Ctl动作有几个自己的子动作,它能改变交互的引擎配置,而且只能改变当前交互的。MultiMatch规则产生了一种特殊的匹配方式,在每一次转换之后,规则里的运算符都以这种方式执行(通常情况下,当所有的转换完成之后运算符只执行这一次)。可以使用t动作来使用0个或更多的转换,在运算符执行之前对变量进行转换。
Table 5.18. Special actions
Action Description
ctl Change configuration of current transaction(改变当前交互的配置)
multiMatch Activate multi-matching, where an operator runs after every transformation()
t Specify transformation functions to apply to variables before matching(匹配之前指定变量的转换函数)
Miscellaneous actions
Miscellaneous动作包含了不属于任何组的动作。
Table 5.19. Miscellaneous actions
Action Description
append Append content to response body
exec Execute external script(执行外部脚本)
pause Pause transaction(暂停交互)
prepend Prepend content to response body()
status Specify response status code to use with deny and redirect(指定响应状态码deny和redirect)
xmlns Specify name space for use with XPath expressions(为APath表达式指定响应空间)
6 Rule Language Tutorial规则语言使用指南
Introducing simple rules and operators
最简单的规则值指定一个变量和一个正则表达式。下面的例子中,检查request URI,看看能不能和正则表达式模式<script>进行匹配。
SecRule REQUEST_URI <script>
正是由于modsecurity允许一个规则不指定运算符,他会假设正则表达式就是一个运算符,这个简单的规则才能成立。
SecRule REQUEST_URI "@rx <script>"
注意因为第二个参数含有空格,必须使用双引号。Modsecurity支持很多运算符,有些相似,但通常会有不同的执行特点。例如,上面的例子中我使用的正则表达式模式(<script>)还不足以成为一个模式。只是一个字符串而已。因为他不包含任何特殊字符。我也能使用@contains运算符写一个同样的规则:
SecRule REQUEST_URI "@contains <script>"
Working with variables
在一条规则当中你可以指定任意多的变量,只要使用“|”字符他们分开即可。
SecRule REQUEST_URI|REQUEST_PROTOCOL <script>
对集合这个变量来说,包含了一条以上的消息。例如ARGS变量,包含了一个交互中所有的请求参数。你可以使用“:”运算符来指定集合当中的一个成员,下面这条规则只查看名字为p的参数:
SecRule ARGS:p <script>
在同一条规则当中你可以多次使用同一个集合:
SecRule ARGS:p|ARGS:q <script>
实际上,“:”非常有效,使用正则表达式的时候,你可以使用“:”来指定名字,当参数的名字在运行期间会发生改变的时候,这个功能非常有用。下面这条规则会找出所有名字是以字母“p”开头的参数,捕捉密码或者pea这样的参数:
SecRule ARGS:/^p/ <script>
如果你没有限制规则只能访问集合中的某些成员时,modsecurity会认为你会用集合的所有成员。当你不知道一个页面会使用什么参数的时候,使用起来会很handy。并不是所有的结合都可以这么使用(ARGS可以,但是ENV不可以)。但是。。。
例如,当一个请求含有p、q、z三个参数时,ARGS可以如下扩展:
[4] Expanded "ARGS" to "ARGS:p|ARGS:q|ARGS:z".
下面这条规则将会检查除z以外的参数:
SecRule ARGS|!ARGS:z <script>
Combining rules into chains
一个规则中指定一个以上的变量时,可以使用OR逻辑运算符。任一个变量匹配,规则就会匹配。也可以使用逻辑AND把几个规则组合成一个。如果你想写一条规则,实现在p和q两个参数中发现一些东西,规则就匹配,你可以这样写:
SecRule ARGS:p <script> chain
SecRule ARGS:q <script>
这就叫rule chaining,chain这个动作构成了两个或更多的规则链,并有效的建立了带有一个以上的evaluation步骤的一条简单规则。链的第一条规则总是运行,而对子规则来说,只有当同一条链中它前面的规则都运行完了之后他才运行。。。
Operator negation否定运算符
在运算符前面放感叹号“!”,就会得到否定的结果。例如:你想写一条规则,当用户名既不是admin也不是root时规则匹配(与之前的例子目的相反):
SecRule ARGS:username “!@rx ^(admin|root)$”
不要把运算符否定和规则否定混淆。只有当一个规则只对一个变量使用的时候两个才是一样的。但是如果变量多于一个的话,情况就变了:
SecRule ARGS:p|ARGS:q “!@eq 5”
上面的规则只要有一个变量不等于5就会匹配。如果你想写一条规则实现两个变量都不等于5时才进行匹配,你就必须使用规则链:
SecRule ARGS:p "!@eq 5" chain
SecRule ARGS:q "!@eq 5"
Variable counting
提问:如何检查没有出现的一些东西,比如常见的规则,把所有的参数放在一个请求中:
SecRule ARGS <script>
一个请求不含有任何变量时,ARGS会扩展成0个变量。如果没有变量的话,运算符将会运行失败,规则(或规则链)将不会匹配。
答案就是使用modsecurity的能力去计算集合中变量的个数。使用&运算符可以查看ARGS,检测没有参数的情况:
SecRule &ARGS “@eq 0”
&运算符可以应用于任意集合,包括集合的某一部分。下面这条规则当请求中含有一个以上username参数的时候将会匹配。
SecRule &ARGS:username "!@eq 1"
Using actions
目前这个指南中的大部分例子都没有用动作。刚开始我们只关注检测机制。实际上,连一条简单动作都不指定的话,你是写不出规则的。而且,写独立的规则而不是让规则依赖于默认动作,是一个很好的习惯。
SecRule第三个参数和SecAction第一个参数是动作。一个规则可以没有动作,也可以有一个或一个以上的规则。如果有一个以上的动作,用“,”和许多空格进行分隔。下面这条规则指定了两个动作:
SecRule ARGS K1 log,deny
有些动作带有参数,你需要在动作和参数之间放一个“:”。使用状态码404拒绝,规则如下:
SecRule ARGS K1 log,deny,status:404
最后,如果提供的参数带有空格或逗号,需要用单引号把参数值括起来这种参数处理方式经常用于消息中:
SecRule ARGS K1 “log,deny,msg:’Acme attack detected’”
在msg动作参数周围使用单引号之外,我把整个指令参数用双引号括起来了。这样Apache才会正确解析指令行。稍后你将会看到一些动作包含复杂的参数(如ctl和setvar),现在讨论的语法同样要应用于他们。
Understanding action defaults
你已经了解了如何指定规则动作,但是如果你不指定的话会发生什么呢。Modsecurity有一个默认的动作列表。当你在配置中添加新的规则时,这条规则的动作列表和默认动作列表合并。Modsecurity2.5.11中,默认动作类表是phase:2,log,auditlog,pass,但是你可以随时使用SecDefaultAction指令来把它覆盖。最简单的例子是,当增加的规则里面没有动作时,就会替换性的使用默认动作列表。一下面这条规则为例(假设配置中没有其他的规则或默认动作。)
SecRule ARGS K1
相当于:
SecRule ARGS K1 phase:2,log,auditlog,pass
通常当一个规则有一个或一个以上的动作时,合并意味着两件事情中的一件:
Rule action replaces an action in the default action list规则动作代替默认动作列表中的一个动作
这非常典型的发生在disruptive动作中,一个每一条规则只能有一个disruptive动作。如果在默认动作列表中和新的规则中都指定了一个disruptive动作,那么规则中的那个将会把默认的覆盖掉。
Rule action is appended to the ones in the default action list规则动作添加到默认动作列表中去
有些动作会在动作列表中出现不止一次。像很多non-disruptive动作,例如:t,setvar,ctl等等。有些情况下规则动作可以完全去除默认动作,但怎么做到的取决于动作。例如转换动作指定none作为转换函数(t:none)的话,就是清空列表重新开始。
SecDefaultAction phase:2,log,deny,status:404
SecRule ARGS K1
SecRule ARGS K2
…
SecRule ARGS K99
SecADefaultAction phase:2,log,pass,t:lowercase
SecRule ARGS K1 t:urlDecode
#first we have some rules that only warn
SecDefaultAction phase:2,log,pass
SecRule ARGS W1
SecRule ARGS W2
…
SecRule ARGS W19
#Now we have some rules that block
SecDefaultAction phase:2,log,deny,status:500
SecRule ARGS B1
…
SecRule ARGS B89
S
139
9 Practical Rule Writing实用规则写作
Whitelisting白名单
通常写规则集是为了挑选出不寻常的请求,但事实是大多数网络包含一个或多个请求源,这些请求源不仅是不寻常的,而且是所需要的。网络越复杂,就越需要使用白名单。大多数情况下,一个粗陋的监视脚本监视你的网站,看上去更像是一个粗陋的Perl脚本攻击你的网站。你可能会把安全测试外包给第三方,并且你不想你的规则干扰他们的工作。最后,即使你没有这些问题,你也无法避免一些不能预料的情况,Apache会给自己发送请求。
Whitelisting theory
Integration with other Apache modules与Apache其他模块整合
Apache最大的优点就是它的模块化。大多数情况下模块是单独使用的,但是多功能模块能把一个模块与另一个模块联系起来。通常modsecurity避免重复实现一些其他模块已经实现了的功能,即使是带有安全标签的功能。向其他模块发送指令或者从其他模块接收指令需要时间。
Apache内部有两个机制实现模块之间的联系:
Environment variables环境变量
通常内部模块使用环境变量来实现与其他模块之间的信息交换或者相互影响。当两个模块需要联系时,要配置接受状态的模块来监听环境变量,并能对环境变量进行作用。很多模块建立之初就带有环境变量,所以如果你发现一个模块支持环境变量,那就意味着你能够用这个环境变量通过setenv动作和modsecurity的模块进行通信。因为在modsecurity内部你能够实用ENV集合检索已命名变量的值,所以你可以不受限制的使用其他模块提供的信息来写规则。
Optional functions可选函数
对一个模块来说,有了可选函数,就可以输出一个或者更多的函数供其他模块使用。Modsecurity在可选函数顶部建立了自己的扩展API接口。扩展API会在第十三章,Extending Rule Language.详细讲解。
你可能感兴趣的模块包括:
•mod_deflate
• mod_headers
• mod_log_config
• mod_rewrite
• mod_setenvif
Conditional logging有条件的日志记录
通常情况下,日志会把所有Apache处理过的交互都记录下来,但是有时候你只想记录一部分交互。这就是conditional logging。你可以使用Apache的环境变量描述你想记录哪些东西。
• 默认记录 ,但是如果设置了环境变量就不记录
• 默认不记录,但是如果设置了环境变量就会记录
下面的例子,创建了一个自定义访问日志,只记录指定IP地址的交互:
# Detect the condition that require logging
SecRule REMOTE_ADDR "@streq 192.168.1.1" \
phase:1,nolog,pass,setenv:SPECIAL_ACCESS_LOG
# Create a special access log file, which reacts to
# the SPECIAL_ACCESS_LOG environment variable.
CustomLog logs/special_access.log combined env=SPECIAL_ACCESS_LOG
Header manipulation头操纵
Apache用mod_headers模块进行头操纵。Header和RequestHeader指令知道怎样去检查我前面提到的环境变量。也就是说你可以使用Header和RequestHeader指令有条件的改变请求和响应头。像以前一样,用modsecurity检查条件,如果条件符合的话设置环境变量。
Mod_Header模块是一个Apache平台上对请求头和响应头进行定制的模块,它的强大之处是可以和ModSecurity的SetEnv指令联合使用,如:(张宏超)
下面的例子中使用modsecurity引导mod_headers删除session(会话)cookie:
#Simulate a condition that would want us
#to force the user to use another session(模拟一下,强迫用户使用另一个会话)
SecRule ARGS attackPattern “phase:2,t:none,log,pass,setenv:DISABLE_OUTBOUND_SESSION”(当遇到攻击attackPattern时,modsecurity会给mod_headers发送环境变量)
#Expire session cookies when instructed(mod_headers接收到命令时时终止会话cookies)
Header set Set-Cookie “PHPSESSION=;expires=Fri,31-Dec-1999 00:00:00 GMT” \
Env=DISABLE_OUTBOUND_SESSION (当mod_headers接收到环境变量DISABLE_OUTBOUND_SESSION时就会删除会话cookie,并给用户返回另一个会话)
这个例子简单的来说就是当发现某个人在攻击我们的网站时,我们就强制重新给他发一个session(张宏超)
(这个规则编译时候需要有action id号,并且需要在httpd配置文件中加载模块:
LoadModule headers_module modules/mod_headers.so)
Securing session cookies保护会话cookies
在支持用户认证的web应用中,会话cookie功能作为临时口令。用户只提供他们的身份证明一次,假设证明是正确的,将会把他们的会话作为认证标记。从此刻起,只要知道会话ID就可以完全控制这次会话。应该非常小心创建会话cookie,以保证他们的安全。在很多应用中,可以通过修改cookie结构的两个方面提高他们的安全:
Use of the httpOnly flag使用httpOnly标志
Ie发明了httpOnly,目的是防止JavaScript访问会话cookies。攻击者经常使用JavaScript成功实现XSS攻击,然后盗窃会话ID。因为只有服务器编码使用会话cookies,所以如果阻止JavaScript访问并不会损失什么。使用httpOnly会使会话劫持变得更困难。
Use of the secure flag使用secure标志
如果网站使用SSL,攻击者就无法访问在网站和用户之间传输的数据。当使用SSL时,经常忽略了把会话cookies标记为secure。这种疏忽会使用户的会话cookies陷入危险,使攻击者能够访问响应的会话。
如果你使用的是Apache2.2.4或更高版本,你就能够只使用两条mod_headers指令就可以很快的解决上面这些问题。下面的例子使用PHP提高了会话cookies的安全。
# Add missing httpOnly flag
Header edit Set-Cookie "(?i)^(PHPSESSID=.+(?!httponly))" "$1; httpOnly"
# Add missing secure flag
Header edit Set-Cookie "(?i)^(PHPSESSID=.+(?!secure))" "$1; secure"
通常使用Set-Cookie头来创建新的cookies,所以通过查看Set-Cookie头,就可以找出没有设置期望标志的会话cookies。如果找到设置错误的cookie,我们会修改头并加上标志。例子使用了很少用但是很有用的特性:
两个正则表达式都以(?i)开头,保证匹配动作不区分大小写。
第二部分里面,一个negative lookahead assertion(否定先行界定符),造成只有当界定符里面的bits没有在头里面出现时才会匹配整个模式。
第四个参数使用反响引用($1),第四个参数包含的值,会替换现存的Set-Cookie的值,现存的头值会替换反向引用($1)。
Advanced Blocking高级锁定
简单的锁定是直截了当的。
使用deny状态码和redirect(重定向)状态码
配置用户响应页面(单独一个单元还是应用程序安装的一部分?)
不能锁定第五阶段
锁定第三和第四阶段会有困难
加上可能带有mod_deflate的版本
蜜罐锁定(每个IP地址/段重定向)
指定了什么时候锁定但没指定怎么锁定
延迟(阶段)锁定——设置一个标志评估段中的规则。最大化的检测。
基于分数的锁定(每次交互)
持续的基于分数的锁定(每个IP地址,段,用户)
外部锁定
严重性有什么用
可以在锁定中使用标记吗
用于锁定的名誉数据库(rbl)
用于锁定的GeoIP
Making the most of regular expressions充分使用正则表达式
尽管modsecurity支持很多操作符,正则表达式如此强大而且功能广泛,因为在规则中经常见到正则表达式。Modsecurity使用Per1兼容正则表达式库http://www.pcre.org ,更常称为PCRE。这是一个周所周知应用广泛的正则表达式库。Apache也使用的PCRE。正则表达式强大的令你惊奇,你会发现它比你想象的能干。这个章节将会强调PCRE最重要的方面以及modsecurity是如何使用它的,但这也只是冰山一角。强烈建议你熟悉一下PCRE参考资料http://www.pcre.org/pcre.txt ,包含了你需要知道的所有东西。
How ModSecurity Compiles Patternsmodsecurity怎样编译模式
正则表达式需要先编译后使用。编译是转化成有效的内部表示。在configure-time,编译步骤做尽可能多的工作来提高库的性能,编译标志会影响模式的使用,你需要注意一下他们。在最重要的地方,即@rx操作符,使用正则表达式,modsecurity用了两个编译标志:
PCRE_DOLLAR_ENDONLY
默认,一个美元通配符$将会在字符串结尾匹配换行符。用户通常会发现一件不可思议的事情,规则完全控制着哪个地方允许什么东西,但是$却把规则打乱了。通过使用PCRE_DOLLAR_ENDONLY来编译模式,$只能在输入的结尾进行匹配。
以下是从百度文库里搜索的:
D(PCRE_DOLLAR_ENDONLY)
如果设定了此修正符,模式中的行结束($)仅匹配目标字符串的结尾。没有此选项时,如果最后一个字符是换行符的话,也会被匹配在里面。如果设定了m修正符则忽略此选项。
PCRE_DOTALL
默认,模式中的原点元字符匹配除了指定换行符之外的所有字符。在一个有潜在弱点的安全上下文中,攻击者使用换行符打破攻击有效载荷并阻止模式匹配。使用PCRE_DOTALL集,一个原点元字符会真正的匹配任何字符。
现在你知道了要使用哪些编译标志,去了解两个不用的很重要:
PCRE_CASELESS
匹配时忽略大小写。
以下是从百度文库里搜索的:
S(PCRE_DOTALL)
如果设定了次修正符,模式中的原点元字符(.)匹配所有的字符,包括换行符。没有此设定的话,则不包括换行符。
Table 9.1. Pattern compilation flags
Usage Compilation flags used
@rx PCRE_DOLLAR_ENDONLY, PCRE_DOTALL
@verifyCC PCRE_DOTALL, PCRE_MULTILINE
SecAuditLogRelevantStatus PCRE_DOTALL
SecRuleRemoveByMsg No flags used
Variable selection (e.g. ARGS) PCRE_CASELESS, PCRE_DOLLAR_ENDONLY, PCRE_DOTALL
Changing how patterns are compiled改变模式编译的方式
如果你对modsecurity编译模式的方式不满意,但是你会对一件事情感到满意,那就是你可以用PCRE在模式内部可以覆盖编译标志。比如下面这个例子:没有使用任何转换函数,无论使用什么案例,它将会匹配单词attack
SecRule ARGS “(?i)attack” phase:2,t:none
把(?i)部分放在模式开头,为整个模式触发PCRE_CASELESS标志。也可以通过在里面方修饰语的方法,为模式的一部分修改设置。
SecRule ARGS “attack (?i)keyword” phase:2,t:none
上面这个例子将会匹配attack keyword和attack KEYWORD,但不会匹配ATTACK keyword。如果你在次模式中使用修饰语,只修饰余下的模式:
SecRule ARGS “(ken(?i)word) attack” phase:2,t:none
上面的例子将会匹配keyWORD attack,但不会匹配keyWORD ATTACK或者KEYWORD attack。
在字母之前使用破折号-来删除一个标志。下面的模式打乱了modsecurity默认使用的PCRE_DOTALL标志:
SecRule ARGS “(?-s)keyword” phase:2,t:none
你可以用这种方法使用的修饰符的完整列表在表9.2,你可以查阅PCRE参考文件查找他们完整的意思。
Table 9.2. Pattern modifiers
Modifier Meaning
i PCRE_CASELESS
J PCRE_DUPNAMES
m PCRE_MULTILINE
s PCRE_DOTALL
U PCRE_UNGREEDY
x PCRE_EXTENDED
X PCRE_EXTRA
Common pattern problems常见模式问题
正则表达式出错很常见,但是有两个更加常见:
Forgetting to escape the dot metacharacter 忘记忽视元字符点.
很容易遗忘一件事情,那就是点.是一个需要被忽视的元字符。因为IP地址里面有很多点,所以当你写一个模式来匹配IP地址的时候,经常发生这种事情。如果没有忽视点,点将会匹配任意一个字符,和非元字符进行匹配。
Not using the ^ and $ anchors when matching entire input当要匹配整个输入的时候没有使用^和$锚
当你要匹配整个输入的时候,需要使用^和$。者能够保证,不管你写的是什么模式,都能够进行全部匹配。如果你忘记了使用^,攻击者就是在你的模式之前发送任意内容,如果是忘记了使用$,攻击者就会在你的模式之后发送任意内容。如果没有锚,模式将会匹配中间的子字符串,而忽略其他任何东西。
Regular Expression Denial of Service正则表达式拒绝服务攻击
正则表达式拒绝服务攻击(又称ReDoS)是一个比较令人费解的问题,它能影响每一个正则表达式写手。一些正则表达式结构当遇到边界案例的时候性能变得很差(指数级的)。你一不小心会写出一个会被暗中操纵的模式,攻击者从外面消耗你大部分服务器资源。
下面是从Alex’s和Adar’s借用的一些变量模式的例子:
(a+)+
([a-zA-Z]+)*
(a|aa)+
(a|a?)+
(.*a){x},for x>10
Resources
当和正则表达式一起工作的时候会变得不知所措时,不要紧张。完全正常并且会得到及时解决。想要精通正则表达式没必要买书,但是如果买的话肯定会有帮助的。关于书我只关注一点,就是他们都能涵盖大部分正则表达式特性,而且我唯一感兴趣的是PCRE。你至少应该看两本书:
Mastering Regular Expressions。作者:JeffreyFriedl(O’Reilly,2006),普遍认为是正则表达式的经典著作。
Regular Expressions Cookbook,作者:Goyvaerts和Steven Levithan(O’Reilly,2009),是正则表达式最近增加的版本,更适合实践学习。
Part II: Reference Documentation
14 Reference Manual
Configuration Directives配置指令:
下面一节概述了modsecurity所有的指令。大部分的modsecurity指令能被用于Apache内,例如虚拟主机,地址,地址匹配,目录等等,当然还有其他,但是,如果在主配置文件里只能使用一次,这个在下面的章节会详细介绍。
这些规则,和和新规则库,应该放在httpd.conf文件外面,然后用include指令包含进来,这样有利于更新或整合规则。如果你想自己定义一个规则,那么你应该创建一个文件命名为modsecurity_crs_15_customrules.conf然后放在核心规则所在文件夹,这样,你的自定义规则将在ModSecurity标准的核心规则库后调用,但在其他核心规则前调用,这是很有用的,如果你的站用了”allow”指令它可以检查核心规则是否误报。
注意
建议不要修改核心规则文件,除非你把它放在你自己的规则库里,这样当你从ModSecurity更新时会方便些。
SecAction action1,action2,action3
无条件执行动作清单,它只接受第一个也是唯一的一个参数,其这个参数的使用规则与SecRule的第三个参数的使用规则相同,SecAction是你想无条件执行一个动作时的最好选择,这个指令不受任何交互条件的限制,SecRule指定了一些动作,而这些动作的发生是基于请求/响应对数据的检查,当你想执行initcol动作时,这个指令通常被用来初始化持久化集合类。例如:
SecAction nolog,phase:1,initcol:RESOURCE=%{REQUEST_FILENAME}
SecArgumentSeparator character
SecArgumentSeparator ;
指定的字符作为application/x-www-form-urlencoded内容的分隔符,默认是&,非常少的情况下应用会使用分号(;)。这个指令用于后台WEB应用在使用非标准的参数分隔符,如果没有在每一个WEB应用中合理设置这个指令,那么ModSecurity可能无法适当的分析所有的参数,并且规则匹配的效果可能会显著的降低。
SecAuditEngine On|Off|RelevantOnly
配置审计日志引擎的开启与否,On-默认情况下记录所有事务的日志,Off-默认情况下不记录所有事务的日志,RelevantOnly-默认只记录事务中由warning或error触发的日志,或者记录一些特意考虑过的状态码
在当前事务可以通过ctl操作进行设置或修改
以下例子说明不同的审计指令一起使用:
SecAuditEngine RelevantOnly
SecAuditLog logs/audit/audit.log
SecAuditLogParts ABCFHZ
SecAuditLogType concurrent
SecAuditLogStorageDir logs/audit
SecAuditLogRelevantStatus ^(?:5|4\d[^4])
SecAuditLog /path/to/auditlog
SecAuditLog /usr/local/apache/logs/audit.log
定义审计日志文件路径,伴随服务器运行开始,这个文件会以root打开,你不能为非root权限的用户对这个文件或存储这个文件的目录有可写权限。如果串行审计日志格式使用后,这个文件将被用作审计日志条目的存储。如果同时审计日志格式使用这个文件那就被当做索引,并包含所有的审计日志文件创建信息。如果你计划使用同时审计日志并发送审计日志数据到远程主机或商业ModSecurity管理平台,那么你需要配置和使用ModSecurity日志搜集器(mlogc)并使用下述格式去得到审计日志:
SecAuditLog “|/path/to/mlogc/path/to/mlogc.conf”
SecAuditLog2 /path/to/auditlog2
SecAuditLog2 /usr/local/apache/logs/audit2.log
定义同时日志启用下的第二审计日志索引文件路径,在本指令使用之前必须通过SecAuditLog定义主审计日志,另外这个文件仅用于当同时审计日志使用时复制主审计索引文件,不能用于非同时审计日志的情况。
SecAuditLogParts PARTS
SecAuditLogParts ABCFHZ(默认)
定义每个事务中记录到审计日志中的部分。每部分以一个独立的字母表示,当每个字母出现在列表中,也就是指每个事务中的相同部分会被记录,全部列表见下文:
A- 审计日志标题(强制的)
B- 请求标题
C- 请求体(目前只针对请求体存在,并且ModSecurity已经配置成拦截)
D- 为中间人响应头保留,暂未实现
E- 中间人相应题(目前仅对配置了拦截响应体和配置审计日志引擎记录有效)。中间人相应体和实际的相应体相同,除非ModSecurity拦截了中间人响应体,这种情况下,实际相应体会包含出错信息(可能是apache的默认错误信息,也可能是出错文档页面)。
F- 最终响应头(除了日期和服务器标题以外的被apache添加的尽其内容传递信息)。
G- 为实际响应体保留,暂未实现
H- 审计日志索引
I- C部分的替换,使用multipart/form-data编码时,在所有的异常情形下记录与C相同的数据,在这种情况下,会记录假的application/x-www-form-urlencoded内容,这包含参数的相关信息,但不是这个文件的。如果你不想用文件(通常很大)来存储你的审计日志,这是很方便的。
J- 保留。实现后,这部分会包含文件使用multipart/form-data编码上传的信息。、
K- 这部分包含一个完整的列表,按顺序匹配(每行一个),这些规则是完全合格的,从而表明继承默认的动作和操作,从2.5.0开始支持。
Z-最终分界,意味着是条目的最后(强制的)
SecAuditLogRelevantStatus REGEX
SecAuditLogRelevantStatus ^(?:5|4\d[^4])
配置哪些响应状态码与审计日志的目的密切相关,必须将SecAuditEngine设置为RelevantOnly,其参数是个正则表达式。
这个指令最主要的目的是允许你配置审计产生特殊HTTP响应状态码的唯一事务,这个指令通常用于减少审计日志文件的总体大小。记住一点,如果使用了这个参数,那么返回状态码是200的成功攻击事件不会记录。
SecAuditStorageDir /path/to/storage/dir
SecAuditStorageDir /usr/local/apache/logs/audit
配置同时审计日志条目存储时的路径,必须同时设置SecAuditLogType,启动apache潜,需要先创建目录,而且必须让服务器用户运行时可以新建文件。
尽管有了记录日志的机制,还需要确保指定的本地文件系统上有足够的磁盘空间,并且不是在根分区上。
SecAuditLogType Serial|Concurrent
配置使用审计日志记录机制的类型,如果使用Concurrent类型必须指定SecAuditLogStorageDir
Serial-所有的审计日志条目都被存储在主审计日志记录文件中,随意使用是很方便,但是他很慢,因为任何时候只有一个文件被打开也只能写入一条审计日志条目。
Concurrent-审计日志条目被存储于不同的文件中,每个事务一个,如果你要把审计日志数据发送到远程ModSecurity控制主机上就是用Concurrent日志模式。
SecCacheTransformations(Deprecated/Experimental)
SecCacheTransformations On|Off [options]
SecCacheTransformations On “minlen:64,maxlen:0”
控制transformations的缓存,2.5.6开始,缓存是默认关闭的,当时都不赞成开启并降低为实验性。
On-缓存变化(每阶段,每次变化)允许相同的变化只执行一次(默认的)
Off-不缓存任务变化,强制所有的变化都被每一条规则实行生效
有以下可选项(逗号分隔):
Incremental:on|off-启用这个选项后,缓存每一个变化,而不只是最后一个变化(默认:off)
Maxitems:N-缓存N个以内的变化,超过时不再缓存,为0时表示unlimited,对于限制缓存一个使用大数字的ARGS表单这个选项是有用的(默认512)
Minlen:N-缓存变化的值的最小长度(默认32)
Maxlen:N-缓存变化的值的最大长度,为0时表示unlimited(默认:1024)
SeChrootDir /path/to/chroot/dirm
配置web服务器工作的安全目录
这个功能在Windows系统版本上不可用,ModSecurity提供的内部chroot功能在简单配置上工作的很好,举个最简单例子,apache只提供静态页面服务或使用模块提供脚本运行功能。在一些复杂设置时你会遇到一些问题:
1、 DNS查询无法工作(这是因为这一功能在chroot操作后,一经查询就要求加载一个共享库)
2、 你不能使用PHP发送邮件,因为PHP使用sendmail但sendmail在安全目录之外
3、 某些情况下apache会莫名其妙的不干活了(重载)
你需要小心,这个内部chroot功能可能不是100%可用。由于大量默认的或是第三方为apache web服务器提供的模块,他们不可能去校验在内部chroot下是否可用,在没有被限制在安全目录中时,一个apache的模块,工作的很正常。特别是如果你正使用的模块在模块初始化阶段进行fork的(如mod_fastcgi,mod_fcgid,mod_cgid),建议你测试每个apache进行和观察其工作目录,进程根目录,以及所打开的文件列表。考虑一下你的选择,在作出决定。
SecComponentSignature “COMPONENT_NAME/X.Y.Z(COMMENT)”
SecComponentSignature “Core Rules/1.2.3”
扩展组件签名为modsecurity签名,这个指令可以让ModSecurity增加很多有意义的已知组件,完整的签名被记录在事务审计记录中,应该让ModSecurity模块和规则集作家使用,使调试更加容易。
SecContentInjection (on|off)
启用内容注入使用行为附加并加在前面
SecCookieFormat 0|1
选择当前配置文本中使用的cookie格式
0- 使用version 0(Netscape)cookies,这是大部分应用使用的,也是默认值
1- 使用version 1 cookies
SecDataDir /path/to/dir
SecDataDir /usr/local/apache/logs/data
指定连续数据(如ip地址数据,session数据等)存储的路径,initcol、setsid和setuid需要用到这个指令,必须让服务器用户对这个目录可写
SecdDebugLog /path/to/modsec-debug.log
SecDebugLog /usr/local/apache/logs/modsec-debug.log
指定modsecurity调试日志文件的路径
Secdebugloglevel 0|1|2|3|4|5|6|7|8|9
配置冗长的调试日志数据,1~3级别一直用于产生apache的错误日志,因为你可以在产品中一直使用0级别作为默认的日志级别,级别5用于调试,不建议在产品中使用这么高级别的日志,过度的日志记录会显著服务器的性能。
可用的值如下:
0-不记录,1-仅仅错误日志(拦截请求),2-警告,3-注意,4-事务控制的细节,5-同上,但包含每一个信息控制的信息,9-记录所有,包括每一个调试细节信息
SecDefaultAction action1,action2,action3
定义匹配规则后的默认动作,例:
SecDefaultAction log,auditlog,deny,status:403,phase:2
备注:SecDefaultAction指令后的规则都继承这一设置,除非为某条规则制定了一个特定的动作,或者制定了新的 SecDefaultAction。特别注意到,未经处理的disruptive动作时不允许的,但是在SecDefaultAction中一不小心就会继承了使用disruptive动作。
默认值是minimal
SecDefaultAction phase:2,log,auditlog,pass
注意:SecDefaultAction必须指定一个disruptive动作和处理阶段,而且不能包含元数据动作。
警告:SecDefaultAction不集成交叉配置的内容。
SecGeoLookupDb /path/to/db
定义地理数据文件路径,例:
SecGeoLookupDb /usr/local/geo/data/GeoLiteCity.dat 从maxmind.com提取的免费数据文件
SecGuardianLog |/path/to/httpd-guardian
配置使用httpd-guardian脚本来监视拒绝服务攻击(DoS)的指令,例:
SecGuardianLog |/usr/local/apache/bin/httpd-guardian 使用默认的httpd-guardian可以防止客户端在1分钟内请求120次或5分钟内请求360次。
SecGuardianLog,设计此指令用于把所有允许数据通过管理日志功能发送到另一个程序。自从apache部署成典型的多进程方式,信息共享变得困难了,这一想法就是部署一个独立的外部进行使用状态机的方式去观察所有的请求,提供额外的保护。
随着ModSecurity发布,开发一个先进的外部保护工具将是一个重点。然而一个完整功能的工具已经可以做为apache httpd工具项目的一部分,工具名为httpd-guardian,它能用于防御DoS,使用黑名单列表(同一个项目中)和基于iptables(linux)或者基于pf(*BSD)的防火墙协同工作,动态的过滤黑名单中的恶意ip地址。也可以和SnortSam协同工作。如果已经配置过httpd-guardian,你只需要在apache配置中添加一行就可以部署他:
SecGuardianLog |/path/to/httpd-guardian
Secmarker ID
Secmarker 9999
在规则集中增加一个固定规则marker,可用于skipAfter动作。Secmarker指令本质上是创建了一条规则,这条规则什么也不做,其目的只是占用一个ID号
SecRule REQUEST_URI “^/$” \
“chain,t:none,t:urlDecode,t:lowercase,t:normalisePath,skipAfter:99”
SecRule REMOTE_ADDR “^127\.0\.0\.1$” “chain”
SecRule REQUEST_HEADERS:User-Agent \
“^Apache \(internal dummy connection\)$” “t:none”
SecRule &REQUEST_HEADERS:Host “@eq 0” \
“deny,log,status:400,id:08,severity:4,msg:’Missing a Host Header’”
SecRule &REQUEST_HEADERS:Accept “@eq 0” \
“log,deny,log,status:400,id:15,msg:’Request Missing an Accept Header’”
SecMarker 99
SecPcreMatchLimit
SecPdfProtect On|Off
启用PDF XSS保护功能,一量启用访问PDF文件的跟踪,直接访问尝试被转到包含一次性令牌的链接,只有提供有效令牌的请被无条件允许,无效令牌的请求也被允许,但被强制下载PDF文件。本实现用响应头去检测PDF文件,因此可以对一些URI请求中不含有.pdf扩展名却能动态生成PDF文件。
SecPdfProtectMethod method
SecPdfProtectMethod TokenRedirection(默认)
配置理想的保护方法用于请求的PDF文件进行保护。可有的选项有TokenRedirection和ForcedDownload。令牌重定向方式会尝试转到可有的令牌上,这允许PDF文件仍旧能使用内联方式打开,但仅用于GET请求方式。强制下载总是导致PDF文件使用二进制或附件方式传递,后者常用于非GET请求,强制下载方式被认为更安全,但对用户来说可能会导致可用性问题(“这个PDF无法再打开了”)。
SecPdfProtectSecret secret
secPdfProtectSecret MyRandomSecretString
定义用户产生一次性令牌的密钥,你应该设置一个足够长的串作为密钥(16字符较好),一旦定下密钥,最好不要修改,可能会破坏修改前发出的令牌。但即使你修改了也不是大问题,导致过去的几秒钟变成使用令牌强制下载PDF文件。
SecPdfProtectTimeout timeout
SecPdfProtectTimeout 10(默认)
定义令牌超时,令牌过期后,不能再用于允许访问PDF文件,请求仍旧被允许,但PDF文件会以附件方式传送。
SecPdfProtectTokenName name
SecPdfProtectTokenName PDFTOKEN(默认)
定义令牌名,你想改变令牌的名字的唯一原因应是你想隐藏你正使用ModSecurity这一事实,这是一个好的理由,但这并不是提供帮助,因为敌人能找到保护PDF的算法并能计算出来,这树立了新的标志,所以如果你想就去试吧。
SecRequestBodyAccess On|Off
ModSecurity是否默认缓存并处理请求体,On-访问请求体,Off-不访问请求体。
注意:当你想检查POST_PAYLOAD时使用这个命令,这个指令必须和“phase:2”和REQUEST_BODY一起使用,这三部分任一一个没有配置,你就无法检查请求体。
SecRequestBodyLimit NUMBER_IN_BYTES
SecRequestBodyLimit 134217728
配置ModSecurity允许的最大请求体的缓存区大小,默认值是131072KB(134217728bytes)。任何超过此限制的都会被拒绝,提示413,请求体太大。还有一个应限制,1GB。
SecRequestBodyNoFilesLimit NUMBER_IN_BYTES
配置ModSecurity允许的最大请求体的缓存区大小,除了请求中正在传送的文件大小。这项指令便于在受到某些使用大尺寸请求进行DoS攻击时减少影响。提供上传文件服务的WEB应用必须配置SecRequestBodyLimit为一个很大的值。由于大文件直接进行磁盘文件存取,不会加大内存的消耗。但是,仍然有可能有人利用超大请求体限制和发送大量大小的非上传请求。该指令消除这一漏洞。
SecRequestBodyLImit 131072
备注:默认为1MB(1048576 bytes)。这个值比较古老了,大部分应用应该到128KB或者更低,任何超过此限制的都会被拒绝,提示413,请求体太大。还有一个应限制,1GB
SecRequestBodyInMemoryLimit NUMBER_IN_BYTES
SecRequestBodyInMemoryLimit 131072
配置ModSecurity使用内存保存的最大请求体大小,默认的限制是128KB,在内存中最多存储128KB。
SecResponseBodyLimit NUMBER_IN_BYTES
SecResponseBodyLimit 524228
配置允许缓存的最大相应体大小,任何超过此限制的响应都会被拒绝,并出现状态码:500:内部服务器错误。这一设置不影响使用MIME类型的响应,缓存不为此做标记(因为这个类型标记为非缓存),有一个硬编码为1GB。
默认配置成512KB
SecResponseBodyLimitAction Reject|ProcessPartial
Reject 响应体将被丢弃,传输中断,返回状态码:500(内部服务器错误)
ProcessPartial 只检测缓存中的响应,剩下的允许通过
配置SecResponseBodyLimit控制碰到响应体限制的情况,默认时ModSecurity拒绝超过指定长度的响应体,然而一些WEB站点,因为有较大的响应体,所以要指定一个合理的限制很困难。这类网站不得不提升限制,来达到控制首位限制的目的(控制内存消耗)。当达到一个限制,网站管理员有能力选择只检查响应的第一部分,这部分在限制的范围内,剩下的允许通过。有些争辩说,响应的一部分未经检查,就允许通过,是个漏洞,理论上这是对的,但仅适用于攻击者控制输出的情况(如可以使输出任意长)。在这种情况下,防止漏洞是不可能的。攻击者在数据发送回来之前可以压缩,打乱或者加密数据,使数据可以穿越任意监控设备。
SecResponseBodyMImeType mime/type
SecResponseBodyMImeType text/plain text/html
为响应数据缓存配置推荐的MIME类型。可以使用多个SecResponseBodyMimeType指令来增加MIME类型。默认值是text/plain text/html
SecResponseBodyMimeTypesClear
清除推荐的响应体缓存MIME类型,允许你重新开始配置。
SecResponseBodyAccess On|Off
配置响应体是否被缓存并被分析。如果你计划检查HTML的响应,需要使用这个指令。;这个指令必须和”Phase:4”处理阶段动作和REQUEST_BODY变量/位置一起使用,这三部分任意一个没有配置,你就无法检查请求体。可选值如下:
On-访问响应体(仅支持使用MIME类型)
Off-不尝试访问响应体
SecRule VARIABLES OPERATOR [ACTIONS]
SecRule是ModSecurity主要的指令,用于分析数据,并根据结果执行动作。
例子:SecRule REQUEST_URI ”attack” \
”phase:1,t:none,t:urlDecode,t:lowercase,t:normalisePath”
OPERATOR描述如何进行检查
ACTIONS描述当一个操作符成功匹配一个变量时将执行怎样一个动作。
VARIABLES描述哪些变量被检查,举个例子,下述规则则是当地址栏里有“dirty”这个单词时会拒绝交互。
SecRule ARGS dirty
每条规则可以指定一个或多个变量:
SecRule ARGS|REQUEST_HEADERS:User-Agent dirty
还有第三种格式的选择符 –Xpath表达式的支持。Xpath表达式只能用来对付特殊的XML变量,只有请求体使用XML格式时可用:
SecRule XML:/xPath/Expression dirty
注意:不是所有的集合都支持所有的操作符格式,你需要查阅各个集合的文档检查是否支持。
集合Collections
一个变量可以包含一个或多个数据块,这取决于该变量的性质和它的使用方式。当一个变量包含一个以上的值,我们称它为一个集合。
集合在规则运行前都是可以扩展的。如:
SecRule ARGS dirty
可以进行如下扩展:
SecRule ARGS:p dirty
SecRule ARGS:q dirty
在一个请求中只有两个参数,分别为p和q。
集合有几种特性:
只读:
在运行时用交互数据创建,如ARGS(包含所有请求参数值列表)和REQUEST_HEADERS(包含所有请求头值的列表)。
瞬态读/写:
每个交互都创建一个空的TX集合,规则可以从中读取并且可以写入(如使用setvar动作),但在此集合中存储的信息并不持续至交互结束。
连续的读/写:
有几个集合能被写入并且持久存储。这些集合可在交互中跟踪客户,例如IP、SESSION和USER等类型的集合。
规则里的操作符:
最简单的请况是用一个正则表达式作为规则的第二个参数,我们已经在上面举过这样的例子,如果你这样做,ModSecurity就假定你要使用rx(正则表达式)操作符,你也可以很明确的通过使用@来指定你想要的操作符,紧跟@之后的是操作符的名字,在规则第二个参数的开头。例如:
SecRule ARGS “@rx dirty”
注意我们为什么必须使用双引号把第二个规则参数括起来呢,这是因为第二个参数里面包含空格。一些带空格字符和数字会跟在操作符名字后面,如果出现非空格的字符,他们将被视为一个特殊的参数作为操作符。这种情况下制定的参数中的正则表达式被作为模式进行匹配。
如果你使用取非操作符取反操作符返回的结果,可以让@处于第二个字符。
SecRule &ARGS “!@rx ^0$”
取非操作符:
操作符的结果可以通过在第二个字符前使用感叹号来取反,下述规则匹配在User-Agent请求头中找不到dirty单词:
SecRule REQUEST_HEADERS:User-Agent !dirty
你能用感叹号与任一个参数联合使用,这样做,感叹号优先,后面跟上明确的操作符说明,下述规则与前面的例子有相同的效果。
SecRule REQUEST_HEADERS:User-Agent “!@rx dirty”
如果你在多个变量中使用取非操作符,者可呢过无法立即清楚将会发生什么情况,考虑下述例子:
SecRule ARGS:P|ARGS:Q !dirty
这个规则与下面意思相同
SecRule ARGS:p !dirty
SecRule ARGS:q !dirty
警告:取非针对单个操作符,而不是针对整个变量列表。
规则中的动作:第三个参数,ACTIONS可以忽略,因为有个辅助功能,即他可以在默认的动作清单中指定。如果这个参数没有被忽略,当规则匹配时,这个参数指定的动作会联合默认的动作列表创建一个实际的动作列表被执行。
SecRuleInheritance On|Off
配置当前环境是否继承父节点环境(大部分情况下都配置成可继承,你应当查一下文档的每一个指令,已明确他继承与否),On从父环境下继承规则,Off-不从父环境下继承规则。
指定资源的环境(如:Location,Directory,等)不能覆盖主服务器或虚拟服务器上配置的phase1规则。这是因为phase1在请求处理进程之前运行,早于apache分发请求的资源,虚拟服务环境可以覆盖主服务器配置的phase1规则。
例如:下面的例子显示了在主apache配置范围的哪个地方启用ModSecurity,不过,你可以为你的虚拟主机做不同的配置。第一个例子中,头一个虚拟主机没有继承ModSecurity的主配置指令,而第二个做到了。
SecRuleEngine On
SecDefaultAction log,pass,phase:2
…
<VirtualHost *:80>
SerberName app1.com
ServerAlias www.app1.com
SecRuleInheritance Off
SecDefaultAction log,deny,phase:1,redirect:http://www.site2.com
…
</VirtualHost>
<VirtualHost *:80>
ServerName app2.com
ServerAlias www.app2.com
SecRuleInheritance On SecRule ARGS “attack”
…
</VirtualHost>
注意:Configuration Sections是apache的一个概念,指令<Directory>,<Files>,<Location>和<VirtualHost>都是用于创建Configuration Sections的,更多的信息请看apache的文档部分中的Configuration Sections
SecRuleEngine On|Off|DetectionOnly
配置规则引擎,On-处理规则,Off-不处理规则,DetectionOnly-处理规则但不中断交互,即使规则这样配置了也不去执行。这个指令针对每一条规则处理也可以通过ctl动作进行控制(ctl:ruleEngine=off)
SecRuleRemoveById RULEID ACTIONLIST
SecRuleRemoveById 1 2 “9000-9010”
SecRuleRemoveById 1 2 5 10-20 “400-556” 673
使用ID方式从上级环境中删除规则,这个指令支持多个参数,每个参数可以使一个规则ID,也可以是范围。带有空格的参数必须使用双引号括起来。
SecRuleRemoveByMsg REGEX
SecRuleRemoveByMsg “FAIL”
使用规则方式从上级环境中删除规则,这个指令支持多个参数,每个指令是一个应用于消息的正则表达式(指定使用的消息动作)
SecRuleScript(试验性的)
SecRuleScript /path/to/script.lua [ACTIONS]
SecRuleScript ”/path/to/file.lua” “block”
这个指令创建一个特殊的规则,执行lua脚本来决定是否匹配,和SecRule主要的不同是这个没有目的也没有操作符,这个脚本可以从ModSecurity环境中取到所有的变量,并使用(Lua)操作符来进行测试,第二个参数可选,与SecRule相同,是一个动作列表。
注意:所有的 Lua脚本在配置时进行编译并存入内存,要重载脚本,你必须通过apache重启来重载整个ModSecurity配置。
示例脚本:
---------------Your script must define the main entry
---------------pointl,as below.
Function main()
----------Log something at level 1.Normally you shouldn’t be
----------logging anything,especially not at level 1,but this is
----------jusy to show you can.Useful for debugging.
m.log(1,”Hello world!”);
--------------Retrieve one variable.
Local var1 = m.getvar(“REMOTE_ADDR”);
--------------Retrieve one variable,applying one transformation function.
--------------The second parameter is a string.
Local var2 = m.getvar(“ARGS”,”lowercase”);
--------------Retrieve one variable,applying several transformation functions.
--------------The second parameter is now a list.You should note that m.getvar()
--------------requires the use of comma to separate collection names from
--------------variable names.This is because only one variable is returned.
Local var3 = m.getvar(“ARGS.P”,{“lowercase”,”compressWhitespace”});
-------------If you want this rule to match return a string
-------------containing the error message.The message must contain the name
-------------of the variable where the problem is located.
-------------return “Variable ARGS:p looks suspicious!”
-------------Otherwise,simply return nil.
Return nil;
End
第一个例子,我仅每次提取一个变量,这种情况下,你需要事先知道变量,然而很多时候,你想检查一些事先不知道的变量名字,就像下面这个例子。
Example showing use of m.getvars() to retrieve many variables at noce:
Function main()
Retrieve script parameters.
Local d = m.getvars(“ARGS”,{“lowercase”,htmlEntityDecode”});
Loop through the parameters.
For I = 1,#d do
Examine parameter value.
If(string.find(d[i].value,”<script”))then
Always specify the name of the variable where the
Problem is located in the error message.
Return(“Suspected XSS in variable” d[i].name..”.”);
End
End
Nothing wrong found.
Return nil;
End
注意:Lua支持被标示试验方式的编程接口可以继续发展,同时我们努力让其最佳方式运行
SecRuleUpdateActionById RULEID ACTIONLIST
SecRuleUpdateActionById 12345 deny,status:403
按ID方式更新指定规则的动作列表,本指令合并指定的动作列表和规则的动作列表,存在两个限制,一是规则ID不能被改变,也不能换阶段。另外还需要注意的是动作可以duo8ci被附加到原来的。
SecAction\
“t:lowercase,phase:2,id:12345,pass,msg:’The Message’,log,auditlog”
SecRuleUpdateActionById 12345
“t:compressWhitespace,deny,status:403,msg:’A new message’”
The example above will cause the rule to be executed as if it was speciafied as follows:
SecAction\
“t:lowercase,phase:2,id:12345,log,auditlog,t:compressWhitespace,deny,status:403,msg:’A new message’”
SecServerSignature “WEB SERVER SOFTWARE”
SecServerSignature “Netscape-Enterprise/6.0”
通知ModSecurity改变响应头令牌数据中当前使用的“Server:”,按指令的先后顺序执行,你必须完整的配置apache ServerTokens指令。通过该指令,ModSecurity会改写服务器签名数据并存入内存空间的数据集中。如果ServerTokens没有完整设置,那么内存空间就没有希望的足够大来存入我们看到的新数据。
SecTmpDir /path/to/dir
SecTmpDir /tmp
配置临时文件创建的路径,需要提供apache用户进程的可写权限,这个目录的位置也是当apache检查数据用完内存时(比SecRequestBodyInMemoryLimit指令指定的还多的数据)会将数据交换到磁盘上的位置。
SecUploadDir /path/to/dir
SecUploadDir /tmp
配置拦截文件存储的目录,这个目录必须和SecTmpDir定义的临时目录在同一个文件系统上,(This directory must be on the same filesystem as the temporary directory defiled with SecTmpDir.This directive is used with SecUploadKeepFiles.)
SecUploadFileMode octal_mode|”default”
SecUploadFileMode 0640
用8进制(和chmod一样)配置所有上传文件的模式(权限),这个功能在不支持8进制文件的操作系统上不可用。默认模式(0600)仅允许有读写许可的账号修改这个文件,如果其他账号也需要访问(使用clamd是个好例子),那么这个指令时必须的。不管怎样,要慎用这个指令,避免将敏感数据显露给未授权用户,使用“default”值时,还原默认设置。
SecUploadKeepFiles On|Off|RelevantOnly
配置是否保存事务处理后的拦截文件,该指令要求已经定义存储目录(使用SecUploadDir),On-保存上载文件,Off-不保存上载文件,RelevantOnly-只保存被确认与请求有关的文件
SecWebAppId “NAME”
SecWebAppId “WebApp1”
创建服务器上的一个分区只属于一个WEB应用,通过使用分区来避免会话ID和用户UD之间的冲突,在同一台服务器上部署多个应用时一定要使用这个命令,如果不使用,会话ID之间的冲突可能发生,默认值是default
<VirtualHost *:80>
ServerName app1.com
ServerAlias www.app1.com
SecWebappId “App1”
SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
…
</VirtualHost>
<VirtualHost *:80>
ServerName app2.com
ServerAlias www.app2.com
SecWebAppId “App2”
SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
…
</VirtualHost>
配置显示了两个例子,SecWebAppId与apache的VirtualHost指令协同工作,在一台服务器上应创建各自独特的集合名称,一般情况下,当启用setsid时,ModSecurity会使用”SESSION”的值来创建集合,这可以保存专用值,然而像上述例子一样使用SecWebAppId,集合的名字会变成”App1_SESSION”和”App2_SESSION”。
SecWebAppId相关的两个情况:
1、你正把事务(transactions)和报警记录到ModSecurity Console(控制台)上,并且你想用WEB应用ID来搜索仅属于那些应用的事务。
2、你正使用数据留存设施(SESSION和USER集合)并且你需要在属于不同的应用之间的会话和用户之间避免冲突。
处理阶段:
ModSecurity 2.x允许把规则至于下述五个阶段之一:
请求头(REQUEST_HEADERS)
请求体(REQUEST_BODY)
响应头(RESPONSE_HEADERS)
响应体(RESPONSE_BODY)
记录(LOGGING)
为了在规则执行时选择阶段,需要使用阶段命令,可以通过规则中直接使用,也可以通过SecDefaultAction指令。
SecDefaultAction “log,pass,phase:2”
SecRule REQUEST_HEADER:Host “!^$””deny,phase:1”
注意:要注意规则的执行时依赖于阶段,即使是一个配置文件中的两条邻近的规则,只要是设置了在不同的阶段中执行,他们就不会是一个接一个的生效。配置文件中的规则顺序仅仅是在规则各自的阶段中是重要的。在使用Skip和SkipAfter动作时尤为重要。
注意:LOGGING阶段比较特别,无论前面的各个阶段发生了什么事,都会每个事务的最后被执行。这就意味着哪怕是请求被中断或是放行事务时都会被执行。
请求头阶段:
这个阶段的规则会在apache完成请求头的读取后立即被执行(post-read-request阶段),这时,还没有读取请求体,意味着不是所有的参数都可用。如果你必须让规则尽早运行,应把规则放在这个阶段(在apache使用这个请求做某些事前),在请求体被读取前做些事情,从而决定是否缓存这个请求体,或者决定你将希望这个请求体如何被处理(如是否以XML格式解析或不解析)。
注意这个阶段的规则无法影响apache的范围指令(Directory,Location,LocationMatch等)像post-read-request钩子一样还无法得到信息。VirtualHost指令有些例外,如果想在apache的locations使用ModSecurity规则,那么他们应该运行在阶段2,参考apache请求环/ModSecurity处理阶段图标。
请求体阶段:
这是通用输入分析阶段,大部分传统的应用规则不在这儿,这个阶段你肯定能收到参数(只有读取过请求体后),在请求体阶段,ModSecurity支持三种编码类型。
Application/x-www-form-urlencoded – used to transfer from data
Multipart/from-data – used for file transfers
Text/xml – used for passing XML data
大部分WEB应用还没有使用其他的编码方法。
响应头阶段:
发生在响应头被发送到客户端之前,如果你想观察响应发生前就在这儿运行,如果你想使用响应头来决定你是否想缓存响应体也行。注意一些响应状态码(如404)在请求环的早期就被apache管理着,我也无法触发预期。加上apache在后面的钩子上双增加了一些响应头(如日期、服务器和连接信息等),这些我们无法触发和审查。在代理配置模式下或使用phase:5(logging)工作的较好。
响应体阶段:
这是通用输出分析阶段,这里你能运行规则截断响应体(当然提供缓存)。这个阶段你想检查输出的HTML信息公布、错误信息和失败的验证文字。
日志阶段:
在日志发生前运行的一个阶段,放在这个阶段的规则只能影响日志记录器如何执行,这个阶段可以检测apache记录的错误信息,在这个阶段你不能拒绝或阻断连接,因为太迟了,这个阶段也允许检测其他的响应头,如那在phase:3或者phase:4阶段中不可用的。注意在这个阶段,你应当小心不要继承破坏性的动作到规则中,这样的情况在ModSecurity2.5.0及其以后的版本中被当做配置错误。
Variables变量
Modsecurity2.x支持的变量:
ARGS
是一个集合,可以作为静态参数(以名称为匹配论点)方式或以正则表达式(以正则表达式匹配的所有匹配的论点名称)方式用于它自身(意思为POST负载中的所有论点)
一些变量是事实上的集合,在运行时可以扩展更多的变量
SecRule args dirty 测试所有的请求论点
SecRule ARGS:p dirty 有些时候只想看看集合的一部分,这个例子是通过selection操作(colon)查看名为P的变量(注意:通常行情况下,请求可以包含多个同名的变量)
ScRule ARGS|!ARGS:z dirty 指定排除方式,将仔细检查所有的请求参数是否有单词dirty,除了名字为z的参数(再则,z参数可以为0个,也可以为多个)
SecRule &ARGS !^0$ 统计一个集合中有多少个变量,如果一个请求中使用了0个以上的参数,下面的规则就会有效果(暂时忽视了第二个参数)
SecRule ARGS:/^id_/ dirty 有些时候你需要查看一个参数数组,每个名字只有稍微不同,这种情况下,你可以为集合操作符自己制定一个正则表达式,这个规则就是查阅所有以id_打头的参数名字。
注意:如果参数p不存在,则使用ARGS:p不会对操作符调用起到任何作用。
ARGS_COMBINED_SIZE
此变量相比apache的LimitRequest指令允许你更有针对性的设置Arguments 的总大小,如你可以创建一条规则确保参数数据的大小小于一个特定的阀值(帮助防止缓存溢出问题)例如:如果参数的大小超过25个字符就阻断他。
SecRule REQUEST_FILENAME “^/cgi-bin/login\.php”\
”chain,log,deny,phase:2,t:none,t:lowercase,t:normalisePath”
SecRule ARGS_COMBINED_SIZE “@gt 25”
ARGS_NAMES
是参数名的集合,你可以搜索你想阻断的特定的参数名,在一个积极策略情况下,你也可以仅仅使用白名单(使用!可以反转规则)来审计参数名。例:下例规则仅允许规则名为p和a的两个参数,如果有其他参数名字在其中,就会被阻断。
SecRule REQUEST_FILENAME “/index.php”\
”chain,log,deny,status:403,phase:2,t:none,t:lowercase,t:normalisePath”
SecRule ARGS_NAMES “!^(p|a)$” “t:none,t:lowercase”
ARGS_GET
类似于ARGS,但仅针对于查询字符串中包含的参数
ARGS_GET_NAMES
类似于ARGS_NAMES,但仅针对于查询字符串中包含的参数
ARGS_POST
类似于ARGS,,但仅针对于POST字符串中包含的参数
ARGS_POST_NAMES
类似于ARGS_NAMES,但仅针对于POST字符串中包含的参数
AUTH_TYPE
这个变量保存认证方法用于验证一个用户,注意:这个数据在使用非本地认证的代理模式部署时不可用,在代理模式部署下,你需要检查REQUEST_HEADERS认证头
ENV
是个集合,规则一个单独的参数(在colon后),ENV变量通过setenv设置,不提供CGI环境变量的访问,例如:
SecRule REQUEST_FILENAME “printenv” pass,setenv:tag=suspicious
SecRule ENV:tag “suspicious”
FILES
是个集合,包含一系列的初始文件名(就如同在远程用户的文件系统上命名的一样),注意:只有从请求体中提取的文件才是有用的,例:
SecRule FILES ”\.conf$” log,deny,status:403,phase:2
FILES_COMBINED_SIZE
单一值,所有上传文件大小的总和,注意:只有从请求体中提取的文件才是有用的,例:
SecRule FILES_COMBINED_SIZE “@gt 1000”log,deny,status:403,phase:2
FILES_NAMES
W/O参数集合,包含用于文件上传的表单字段列表,注意:只有从请求体中提取的文件才是有用的,例:
SecRule FILES_NAMES “^upfile$” log,deny,status:403,phase:2
FILES_SIZES
集合,包含文件尺寸的列表,用于实施单独文件上传的大小限制。注意:只有从请求体中提取的文件才是有用的,例:
SecRule FILES_SIZES “@gt 100”log,deny,status:403,phase:2
FIELS_TMPNAMES
集合,包含磁盘上临时文件名的集合,和@inspecFile一起使用,注意:只有从请求体中提取的文件才是有用的,例:
SecRule FILES_TMPNAMES “@inspectFile /path/to/inspect_script.pl”
GEO
是和@geoLookups操作符一起使用的集合,可以用于匹配地理位置字段进行IP或主机名字的查询,2.2.0以后版本可用
字段:
COUNTRY_CODE:两个字符的国家代号,如:US、UK等
COUNTRY_CODE3:升级为3个字符的国家代号
COUNTRY_NAME:完整的国家名
COUNTRY_CONTINENT:两个字符的国家所在洲的代号,如EU
REGION:两个字符表示的区域,对美国来说是州,对加拿大来说是省,等等
CITY:城市名
POSTAL_CODE:邮政编码
LATITUDE:纬度
LONGITUDE:经度
DMA_CODE:中心城区代码(仅指美国)
AREA_CODE:电话区号(仅指美国)
例如:
SecRule REMOTE_ADDR “@geoLookup” “chain,drop,msg:’Non-UK IP address’”
SecRule GEO: COUNTRY_CODE “!@streq UK”
HIGHEST_SEVERITY 这个变量是迄今为止所有规则匹配时最为严格的,Severities是个数值,和比较操作符一起,如@It等
注意:更高的severities,其数值越小,255表示没有设置severitySecRule
HIGHEST_SEVERITY “@le 2” “phase:2,deny,status:500,msg:’severity
%{HIGHEST_SEVERITY}’”
id
说明:对规则指定一个唯一的ID或链。
动作组:元数据
例如:
SecRule &REQUEST_HEADERS:Host "@eq 0" \ "log,id:60008,severity:2,msg:'Request Missing a Host Header'"
注意
这些是保留的范围:
1-99,999;本地(内部)保留,使用你认为合适的但是不要在规则里使用这个范围的因为他们已经分配给其他。
100,000-199,999;,引擎内部保留使用,分配给没有明确标识的规则。
200,000-299,999;modsecurity.org规则保留。
300,000-399,999;gotroot.com规则保留。
400,000-419,999;未使用(可预约)。
420,000-429,999;为ScallyWhack保留。
430,000-699,999;未使用(可预约)。
700,000-799,999;为伊万里斯蒂奇保留。
900,000-999,999;为核心规则项目保留。
1000000及以上;未使用(可预约)。
initcol
说明:初始化一个持久的集合,从存储里导入数据或在内存中创建一个新的集合。
动作组:非中断性
例如:下面的例子启动IP地址跟踪。
SecAction phase:1,initcol:ip=%{REMOTE_ADDR},nolog
注意:通常你想在第一阶段和initcol一起使用以便这个集合在所有阶段都可用。
集合在initcol动作开始被加载进内存。这个集合在存储里将是持续的(并且相应的计数器增加)除非它在交互过程中改变了。请参考” Persistant Storage”以获取得多内容。
REQUEST_COOKIES
这个变量是一个所有cookie数据的集合。例如:下面的例子使用Ampersand(符号&)特殊运算符计算集合中变量的个数。如果请求不包括任何Cookie头的话,规则将会启动。
SecRule &REQUEST_COOKIES “@eq 0”
REQUEST_COOKIES_NAMES
这个变量是一个请求头中cookie名字的集合。例如:如果没有JSESSIONID cookie的话,下面的规则将会启动。
SecRule &REQUEST_COOKIES_NAMES:JSESSIONID “@eq 0”
REQUEST_FILENAME
这个变量包含去掉QUERY_STRING那一部分之后的相对REQUEST_URI(例如/index.php)
SecRule REQUEST_FILENAME “^/cgi-bin/login\.php$” phase:2,t:none,t:normalizePath
注意:anti-evasion交互并不默认在REQUEST_FILENAME上使用。
RESPONSE_HEADERS
这个变量和REQUEST_HEADERS变量相似,可以在同样的manner(方法)中使用,例如:
SecRule RESPONSE_HEADERS:X-Cache “MISS”
注意:这个变量不能访问嵌入式模式中的一些头。在Apache钩子里面加上了像Server,Data,Connection和Content-Type这些头,然后向客户端发送数据。无论是在ModSecurity phase:5还是运行在代理模式下,这些数据都应该是可访问的。
RESPONSE_HEADERS_NAMES
这个变量是一个响应头名字集合。例如:
SecRule RESPONSE_HEADERS_NAMES “Set-Cookie”
注意:和RESPONSE_HEADERS一样,不能访问嵌入式模式中的一些头。
SESSION
这个变量是一个集合,setsid执行完之后才能访问它。例如:下面的例子说明了怎么用setsid初始化一个SESSION集合,怎么使用setvar增加session.score的值,怎么设置session.blocked的值,最后怎么拒绝基于session.blocked的值的集合。
SecRule REQUEST_COOKIES:PHPSESSID !^$ chain,nolog,pass
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
SecRule REQUEST_URI “^/cgi-bin/finger$” \
“phase:2,t:none,t:lowercase,t:normalizePath,pass,log,setvar:session.score=+10”
SecRule SESSION:SCORE “@gt 50” “pass,log,setvar:session.blocked=q1”
SecRule SESSION:BLOCKED “@eq 1” “log,deny,status:403”
SESSIONID
这个变量使用setsid设置的一个值,例如:
SecRule SESSION !^$ chain,nolog,pass
SecRule REQUEST_COOKIES:PHPSESSID !^$
SecAction setsid:%{REQUEST_COOKIES.PHPSESSID}
TIME
这个变量含有一个表示时间的格式化字符串(时:分:秒),例如:
SecRule TIME “^(([1](8|9))|([2](0|1|2|3))):\d{2}:\d{2}$”
TX
交互集合。用来储存数据块,创建交互异常计算等。交互变量用来设置1号请求/响应循环。计算和赋值将不会持续到越过当前请求/响应处理过程。例如:在这个例子中,使用setvar使tx.score增加5个点。紧接着计算这次请求的交互分数,并决定是否去允许/拒绝请求通过。
下面是TX集合的保留名称:
TX:0----捕捉动作中使用@rx或者@pm操作符时的匹配值
TX:1-9-------捕捉括号和捕捉动作中使用@rx操作符时的捕捉子表达式的值。
SecRule WEBSERVER_ERROR_LOG “does not exist” “phase:5,pass,setvar:tx.score=+5”
SecRule TX:SCORE “@gt 20” deny,log
XML
可独立使用(作为validateDTD和validateSchema的目标),也可和XPath表达式参数(这可以使他对任何可接受纯文本的函数来说都是有效目标)一起使用。
DecDefaultAction log,deny,status:403,phase:2
SecRule REQUEST_HEADERS:Content-Type ^text/xml$ \
Phase:1,t:lowercase,nolog,pass,ctl:requestBodyProcessor=XML
SecRule REQBODY_PROCESSOR “|^xml$” skipAfter:12345
SecRule XML:|employees/employee/name/text() Fred
SecRule XML:|xp:employees/employee/name/text() Fred \
Id:12345,xmlns:xp=http://www.example.com/employees
第一个XPath表达式不使用命名空间。他将和类似如下的载荷进行匹配:
<employees>
<employee>
<name>Fred Jones</name>
<address location=”home”>
<street>900 Aurora Ave.</street>
<city>Seattle</city>
<state>WA</state>
<zip>98115</zip>
</address>
<address location=”work”>
<street>2011 152nd Avenue NE</street>
<city>Redmond</city>
<state>WA<state>
<zip>98052</zip>
</address>
<phone location=”work”>(425)555-5665</phone>
<phone location=”home”>(206)555-5555</phone>
<phone location=”mobile”>(206)555-4321</phone>
</employee>
</employees>
第二个XPath表达式使用命名空间。它将匹配以下负载:
<xq:employees xmlns:xp=”http://www.example.com/employees”>
<employee>
<name>Fred Jones</name>
<address location=”home”>
<street>900 Aurora Ave.</street>
<city>Seattle</city>
<state>WA</state>
<zip>98115</zip>
</address>
<address location=”work”>
<street>2011 152nd Avenue NE</street>
<city>Redmond</city>
<state>WA</state>
<zip>98052</zip>
</address>
<phone location=”work”>(425)555-5665</phone>
<phone location=”home”>(206)555-5555</phone>
<phone location=”mobile”>(206)555-4321</phone>
</employee>
</xp:employees
注意第二个例子中的命名空间
Transformation functions转换函数(应用,功能):
当ModSecurity接收到请求或者响应消息,它将把这个消息数据复制到内存当中做备份。交互函数就应用于这个数据。原始请求/响应数据不会被修改。一个变量要先使用交互函数转换之后,才能在规则中进行测试。
注意:ModSecurity之前的版本并没有默认交互函数。
下面的规则将防止攻击者不使用混合大小写(mixed case)来逃避ModSecurity的规则。
SecRule ARGS:p “xp_cmdshell” “t:lowercase”
同一条规则中可以使用多重交互动作,比如下面的规则也能保证攻击者不使用URL编码(%xx编码)逃避规则。注意交互函数的命令能保证一个URL编码信件是第一次编码,而不是转换成小写。
SecRule ARGS:p “xp_cmdshell” “t:urlDecode,t:lowercase”
可以使用SecDefaultAction命令来为每条规则保证转换发生,直到下一条规则。注意交互动作时附加(additive)的,所以如果一条规则明确的列出动作,SecDefaultAction中的转换动作仍然执行。
SecDefaultAction t:urlDecode,t:lowercase
下面是被支持的转换函数:
HtmlEntityDecode
对输入的HTML实体进行解码。支持以下变型:
&#xHH and &#xHH;(H是十六进制)
&#DDD and &#DDD;(D是十进制)
" and "
  and
< and <
> and >
这个函数可以把任何实体转换成一个简单的字节,可能会导致信息丢失。有利于发现本来不需要编码的字节。这个函数不能处理255以上的字符。
lowercase
这个函数使用current C locale把所有字符转换成小写。
none
不是一个转换函数,命令ModSecurity删除与当前指令结合的所有转换函数。
TrimLeft
删除输入左边的空格。
TrimRight
删除输入右边的空格。
trim
删除输入左右两边的空格。
urlDecode
这个函数为URL编码的输入字符串解码。无效编码(例如非十六进制字符,字符串结尾部分少了一两个字符)不会被转换。可以用@validateUrlEncoding运算符检测是否是无效编码。交互函数不能针对URL编码的变量使用,除非你想执行URL二次编码。
urlDecodeUni
除了urlDecode对%xx解码之外,urlDecodeUni需要解码%uXXXX。如果编码在FF01-FF5E(ASCII码总宽度),那么高字节将检查和并调整低字节。否则,只有低字节可用,高字节不可用。
urlEncode
对输入数据进行URL编码
Actions
有五个动作组,每个动作分别属于一个组:
Disruptive actions
引起modsecurity做些事情。有些情况下这些事情意味着锁定事务,但并不是所有情况都这样做。例如,allow动作属于一个disruptive动作组,但是它并不锁定事务。每个规则中只能有一个disruptive动作(如果有多个disruptive动作,或者继承的动作,只有最后那个有效)。每个规则链中也只能有一个disruptive动作(在一个链中,只能在第一条规则中有disruptive动作)。
Non-disruptive actions
做一些事情,但是这些事情并不能影响规则处理流。例如,设置一个变量,或者改变变量的值。任何规则都可以使用Non-disruptive动作,就连一个链中的每一个规则也都可以有Non-disruptive动作。
Flow actions
这些动作影响规则流(例如skip或者skipAfter)
Meta-data actions
使用Meta-data动作可以提供关于规则更多的信息。例如:id,rev,severity和msg。
Data actions
不是真正的动作,只是容器,用来保存其他动作使用的数据。例如,status动作包含了blocking(blocking发生时)使用的状态。
Allow
所属动作组:Disruptive
当成功匹配一个规则时,停止规则的处理(审核)过程,并允许交互继续进行。
SecRule TEMOTE_ADDR “^192\.168\.1\.100$” nolog,phase:1,allow
ModSecurity之前的版本,allow动作只能影响当前的phase。如果在Phase 1阶段中有allow动作,将会跳过phase 1阶段剩下的规则。但是如果在Phase 2阶段中有allow动作,剩下的规则将会继续执行。从2.5.0版本开始,allow动作升级到,可以对正在执行的规则进行细粒度的控制。下列规则适用:
1、像上面的例子中单独使用一个allow的话,allow会影响整个交互,停止当前阶段的处理,而且跳过除了logging阶段之外的其他阶段(logging阶段很特殊,总是执行)。
2、如果和参数phase一起使用,allow将会导致引擎停止处理当前阶段,其他阶段将会照常执行。
3、如果和request参数一起使用,allow将会引起引擎停止处理当前阶段。下一个处理阶段将是RESPONSE_HEADERS阶段。
例如:
#Do not process request but process response
SecAction phase:1,allow:request
#Do not process transaction(request和response)
SecAction phase:1,allow
如果你想让response通过,在RESPONSE_HEADERS阶段使用规则,而且只单独使用allow。
#Allow response through
SecAction phase:3,allow
Capture
动作组:Non-disruptive
当和正则表达式操作符一起使用时,capture创建正则表达式捕捉的副本,并把这些捕捉副本放到交互变量集合里面。每次成功模式匹配,最多只能复制10个,每个以数字0-9的组合命名。
SecRule REQUEST_BODY “username=(\w{25,})” phase:2,t:none,chain
SecRule TX:1 “(?:(?:a(admin|nonymous)))”
注意:数字0捕捉整个的REGEX匹配,1捕捉第一个括号里面的数据。
Chain
动作组:Flow
动作紧跟着规则时,把规则串起来,得到的结果就是规则链,串起来的规则允许有更多复杂的规则匹配,在这些这些规则匹配中,使用大量不同的变量来创建一个更好的规则,并且有利于防止误报。
#Refuse to accept POST requests that do
#not specify request body length.Do note that
#this rule should be preceeded by a rule that verifies
#only valid request methods(e.g.GET,HEAD and POST)are used.
SecRule REQEST_METHOD ^POST$ chain,t:none
SecRule REQUEST_HEADERS:Content-Lenth ^$ t:none
注意:
在程序语言概念中,串起来的规则有点类似于AND条件声明。只有当所有的变量检查返回正数时,规则链中第一部分指定的动作才被触发。只要规则链有一方面是负的,那整个规则链都是负的。同时要注意,disruptive动作,execution段,metadata动作(id,rev,msg),skip,skipAfter动作只能通过链开始规则指定。
deny
所属动作组:Disruptive
停止规则处理过程,并且中断交互。
所属动作组:Disruptive
Id
动作组:Meta-data
给规则或链指定一个ID号
SecRule &REQUEST_HEADERS:Host “@eq 0” \
“log,id:60008,severtity:2,msg:’Reqest Missing a Host Header’”
注意:
保留值范围:
1-99,999::保留做本地(内部)使用,你认为怎么合适就怎么用,但是你分配给别人的规则里面不要用这个范围。
100,000-199,999:引擎内部使用,指定给一些没有明确ID号的规则
200,000-299,999:modsecurity.org发布的规则使用
300,000-399,999:gotroot.com发布的规则使用
400,000-419,999:不可用,仅作保留
420,000-429,999:为ScallyWhack[http://projects.otaku42.de/wiki/Scally-Whack]
430,000-899,999:不可用,仅作保留
900,000-999,999:核心规则[http://www.modsecurity.org/projects/rules/]设计
1,000,000及以上:不可用,仅作保留
Log
一个成功的规则匹配需要被记录。这个动作不仅把匹配记录到Apache error log file(用来记录apache的错误信息)当中也要记录到ModSecurity audit log(调试、审计日志)当中。
msg
动作组:Meta-data
给规则或链指定一个客户消息。
SecRule &REQUEST_HEADERS:Host “@eq 0” \
“log,id:60008,severity:2,msg:’Request Missing a Host Header’”
注意:
Msg消息在错误日志和/或审计日志中,而不作为响应头返回给用户。
noauditlog
所属动作组:Non-disruptive
这个动作表明,当成功匹配一个规则时,并不记录审计日志。不管交互应不应该被记录到aodit log中,这次匹配都不能被当做(下次判断的)标准。(感觉可以用于白名单中)
SecRule REQUEST_HEADERS:User-Agent “Test” allow,noauditlog
注意:如果SecAuditEngine 被设置为On,那么所有的交互都会被记录;如果被设置成RelevantOnly,你才可以使用noauditlog这个动作来控制交互是否被记录。
即使规则里写了noauditlog,规则里触发了审计动作,还是会记录日志,正确的做法是在规则中加上ctl:auditEngine=Off才会不记录日志。(上面是张彪依翻译版的,言简意赅,好理解,我应该感到汗颜)(即使noauditlog这个动作是应用于具体的规则当中,这个规则可能在审计事件触发之前也可能在审计事件触发之后,但是这个交互都要被记录在audit log(审计日志)当中。正确的方法是:使用“ctl:auditEngine=off”来使整个交互的审计都不记录(来使审计记录功能失效)。)
nolog
Action Group:Non-disruptive
不记录规则匹配,既不记录在error中,也不记录在audit logs中。
注意:使用这个动作,也必须说明noauditlog
pass:
动作组:Disruptive
尽管成功匹配了一个规则,但继续检查下一条规则
SecRule REQUEST_HEADERS:User-Agent “Test” log,pass
SecRule中写了pass,SecRule带了multiple targets,每一次规则匹配,所有的target都会被处理,并触发non-disruptive动作。下面的例子里,每一次匹配,TX:test都增加1
SecRule ARGS “test” log,pass,setvar:TX.test=+1
注意:每一次匹配,都不会终止交互,并记录日志,除非阻止日志。
pass
动作组:Meta-data
把规则或规则链归于某一个有效处理阶段之一
SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase
SecRule REQUEST_HEADER:User-Agent “Test” log,deny,status:403
注意:记住如果段是错误的,会导致目标变量为空。即变量或运算符(RegEx)正确,但是由于指定了错误的段,导致丢失恶意数据。
Phase:1
Normally you will want to use phase:1 along with initcol so that the collection is available in all phases.
redirect
动作组:Disruptive
在给定位置发布redirect来拦截交互
SecRule REQUEST_HEADERS:User-Agent “test” \
Log,redirect:http://www.hostname.com/failed.html
注意:如果状态动作是现在时的并且值可接受(为301,302,303,或者307),这个状态码将会用来重定向,否则,状态码302被用来重定向
setvar
动作组: non-disruptive
新建删除更新集合中的变量
新建变量:setvar:tx.score=10
删除变量:setvar:!tx.score
增加减小变量:在数字前面加上+或-:setvar:tx.score=+5
severity
动作组:Meta-data
指定规则的严重性
SecRule REQUEST_METHOD “^PUT$” “id:340002,rev:1,severity:CRITICAL,msg:’Restricted HTTP function’”
注意:
严重值遵循系统日志,如下:
0 EMERGENCY
1 ALERT
2 CRITICAL
3 ERROR
4 WARNING
5 NOTICE
6 INFO
7 DEBUG
用数字或文字值都可以指定严重程度。但是每个数字代表的严重程度很难记忆,所有应该使用文字值指定严重程度。数字值在v2.5.0版本中已经取消了,在接下来的版本更新中也可能会被取消。
skip
动作组:Flow
匹配成功时,跳过一条或更多的规则或规则链、
SecRule REQUEST_URI “^/$” \
“phase:2,chain,t:none,skip:2”
SecRule REMOTE_ADDR “^127\.0\.0\.1$” “chain”
SecRule REQUEST_HEADERS:User-Agent “^Apache \(internal dummy connection\)$” “t:none”
SecRule &REQUEST_HEADERS:Host “@eq 0” \
“deny,log,status:400,id:960008,severity:4,msg:’Request Missing a Host Header’”
SecRule &REQUEST_HEADER:Accept “@eq 0” \
“log,deny,log,status:400,id:960015,msg:’Request Missing an Accept Header’”
注意:skip只应用与当前正在处理的阶段,并且没必要应用于配置文件里面的规则里的命令。如果想通过处理段对规则分类,就要使用skip。不能在一个规则链中跳过规则。一个简单的参数就可以指出要跳过的规则或规则链的数量。
skipAfter
动作组:Flow
匹配后跳过规则或规则链,重新开始执行指定了ID号或marker(参考SecMarker)的规则。
SecRule REQUEST_URI “^/$” “chain,t:none,skipAfter:960015”
SecRule REMOTE_ADDR “^127\.0\.0\.1$” “chain”\
SecRule REQUEST_HEADERS:User-Agent “^Apache \(internal dummy connection\)$” “t:none”
SecRule &REQUEST_HEADERS:Host “@eq 0” \
“deny,log,status:400,id:960008,severity:4,msg:’Request Missing a Host Header’”
SecRule &REQUEST_HEADERS:Accept “@eq 0” \
“log,deny,log,status:400,id:960015,msg:’Request Missing an Accept Header’”
注意:skip只应用与当前正在处理的阶段,并且没必要应用于配置文件里面的规则里的命令。如果想通过处理段对规则分类,就要使用跳过。不能在一个规则链中跳过规则。一个简单的参数就可以指出要跳过的规则或规则链的数量。
status
动作组:Data
与动作deny和redirect动作一起使用来指定响应状态码
SecDefaultAction log,deny,status:403,phase:1
注意:Apache在scope位置(例如Directory,location等)定义的status动作可能会被phase:1的动作设置所代替。如果在配置文件中出现的话,Apache将会触发ErrorDocument指令。所以如果你之前已经为一个给定的状态定义了一个自定义错误页的话,那么这个错误页将会执行并显示给用户。
t
动作组:non-disruptive
当转换功能是针对指定变量,并且变量的结果是由运算符计算得到时,使用动作t
SecDefaultAction log,deny,phase:1,t:removeNulls,t:lowercase
SecRule REQUEST_COOKIES:SESSIONID “47414e81cbbef3cf8366e84eeacba091” \
Log,deny,status:403,t:md5,t:hexEncode
注意:先用SecDefaultAction中指定转换功能,在此基础之上,还需要用SecRule指定转换功能。使用“t:none”可以为某一指定的规则取消所有转换功能。
Operators运算符
规则中可以使用很多运算符,@后面跟运算符名称
eq
相当于等号“=”
SecRule &REQUEST_HEADERS_NAMES “@eq 15”
pm
段匹配运算符。pm使用一组匹配引擎集(Aho-Corasick)来使关键字列表得到更快的匹配,It will match any one of its arguments anywhere in the target value.匹配不区分大小写。
SecRule REQUEST_HEADERS:User-Agent “@pm WebZIP WebCopier Webster WebStripper SiteSnagger ProWebWalker”
上面这个例子中,如果口令在User-Agent HTTP头值中得到匹配,将返回403拒绝访问。
pmFromFile
段匹配运算符。pmFromFile使用一组匹配引擎集(Aho-Corasick)来使关键字列表得到更快的匹配,它和pm相同,不同在于pmFromFile需要一个一列文件作为arguments。目标值将和文件中任一个段相匹配。
注意:1、文件的每一行只能有一个段。行尾标记将会和段剥离,但是段里面不能没有空格(End of line markers will be stripped from the phases,however,whitespace will not be trimmed from phases in the file.)。空行和以“#”开头的行被忽略。
2、使用段文件的相对路径,可以使带有规则集的段文件的内容更简单。此时,包含规则的文件路径被预置为段文件路径。
SecRule REQUEST_HEADERS:User-Agent “@pm /path/to/blacklist1 blacklist2” “deny,status:403”
上面的例子中,如果两个文件的模式(pattern)在User-Agent的HTTP头值中得到匹配,那么403拒绝访问,表blacklist2需要和包含规则的文件相同路径。
validateUrlEncoding
validateUtf8Encoding
检验变量是不是一个有效的UTF-8编码字符串
SecRule ARGS “@validateUtf8Encoding”
注意:UTF-8在大部分web服务器上都是有效的。0-65535之间的整数值用UTF-8字节序列编码,UTF-8字节序列没有百分数。简短的形式只有双字节。
检查以下三类错误:
Not enough bytes.UTF-8支持2,3,4,5,6字节编码。ModSecurity将会找出一个或多个字节丢失的情况。
Overlong characters。ASCII字符直接映射成Unicode(统一字符编码)空间,因而只代表一个简单的字节。但是大多数ASCII字符也能编码成2,3,4,5,6个字符。所有就会欺骗编码者去思考这个字符是不是其他东西(并且这样也大概会防止安全检查)。
SecPcreMatchLimit
SecPcreMatchLimitRecursion
这两个是设置pcre的参数的,用来避免pcre陷入死循环之类的。
pcre是实现正则表达式匹配的库,modsecurity规则里面支持正则表达式,就是用pcre库来做的。
SecStreamInBodyInspection
SecStreamOutBodyInspection
是两个开关,是否检查请求体和响应体。
SecRule REQUEST_HEADERS:Host "^[\d.:]+$" "phase:2,t:none,msg:'Host header is a numeric IP address',severity:1,id:0401006,"
MIME:多功能网际邮件扩充协议
(MIME,Multipurpose Internet Mail Extensions)是一个互联网标准,它扩展了电子邮件标准,使其能够支持非ASCII字符、二进制格式附件等多种格式的邮件消息。
服务器将MIME标志符放入传送的数据中来告诉浏览器使用哪种插件读取相关文件。
MIME能够支持非ASCII字符、二进制格式附件等多种格式的邮件消息。MIME规定了用于表示各种各样的数据类型的符号化方法。浏览器接收到文件后,会进入插件系统进行查找,查找出哪种插件可以识别读取接收到的文件。如果浏览器不清楚调用哪种插件系统,它可能会告诉用户缺少某插件,或者直接选择某现有插件来试图读取接收到的文件,后者可能会导致系统的崩溃。Microsoft公司应用于Windows系统下的浏览器使用ActiveX控件,而不是Netscape插件,这种浏览器不必象其它浏览器那样依靠MIME的编码。"
在HTTP中,MIME类型被定义在Content-Type header中。
在ASP中,设定MIME类型的方法是通过Response对象的ContentType属性。
0601001
#950103
SecRule TX:PARANOID_MODE "@eq 1" "chain,phase:1,t:none,msg:'Path Traversal Attack',id:0601001,severity:1"
SecRule REQUEST_FILENAME|ARGS_NAMES|ARGS|XML:/* "(?:\x5c|(?:%(?:c(?:0%(?:9v|af)|1%1c)|2(?:5(?:2f|5c)|f)|u221[56]|1u|5c)|\/))(?:%(?:u2024|2e)|\.){2}(?:\x5c|(?:%(?:c(?:0%(?:9v|af)|1%1c)|2(?:5(?:2f|5c)|f)|u221[56]|1u|5c)|\/))" "t:none,t:lowercase,capture"