首页 使用教程正文

ModSecurity规则编写入门教程

王子 使用教程 2019-12-11 16863 0

本文将对服务器端接收的数据格式进行分析,以此为出发点来介绍如何编写ModSecurity规则。

ModSecurity官方免费规则可点击此处下载


ModSecurity是对WEB服务端收到的访问数据,以及WEB服务端发送至客户端的数据进行分析判断来进行安全防护,因此我们要了解WEB服务器端接收到的数据格式,ModSecurity的每个变量所对应的是哪部分的数据,以及如何利用ModSecurity对指定的数据进行判断来确定是否拦截。

一、普通请求

WEB请求发送至服务端的数据分为三部分,请求行、请求头、请求体。下方是一次普通WEB请求发送的数据格式:

QQ截图20191214100711.jpg

第一部分为请求行,请求行又包含三个部分:

1.请求方式,如GET、POST、HEAD等;

2.请求URL,包含GET参数,如/index.html,/news/index.php?id=3等;

3.请求协议及版本,如HTTP/1.0,HTTP/1.1等;

如果要利用ModSecurity对请求行的数据进行分析判断,则需要了解对应的变量,本人常用的变量如下:

REQUEST_LINE:代表整个请求行;

#该规则表示,仅允许请求方式为POST,GET以及HEAD,同时请求协议也仅允许为HTTP0.9/1.0/1.1
SecRule REQUEST_LINE "!(^((?:(?:POS|GE)T|HEAD))|HTTP/(0\.9|1\.0|1\.1)$)" "phase:1,id:49,log,block,t:none"


REQUEST_METHOD:代表请求方式;

#该规则表示,如果请求方式是PUT、CONNECT、TRACE、DELETE的任意一种方式,则拦截此次访问
SecRule REQUEST_METHOD "^(?:PUT|CONNECT|TRACE|DELETE)$" "phase:1,id:49,log,block,t:none"


REQUEST_PROTOCOL:代表请求协议及版本;

#该规则表示,如果访问协议不是HTTP,同时协议版本也不是0.9/1.0/1.1的话,拦截此次访问
SecRule REQUEST_PROTOCOL "!^HTTP/(0\.9|1\.0|1\.1)$" "phase:1,id:50,log,block,t:none"


REQUEST_URI:代表包含查询字符串数据在内的完整请求URL,如/news/index.php?id=3;

#该规则表示,如果请求URL中包含attack字符串,则拦截此次访问
#但在判断前会先使用一系列转换函数对REQUEST_URI进行处理
#使用none函数删除与当前规则关联的所有转换函数,使用urlDecode函数进行解码(解码不成功不会报错)
#使用lowercase函数将字符改为小写,使用normalizePath删除多个斜杠、目录自引用和目录反向引用
SecRule REQUEST_URI "attack" "phase:1,id:52,t:none,t:urlDecode,t:lowercase,t:normalizePath"

REQUEST_FILENAME:代表不包含查询字符串数据在内的相对请求URL,即,如果URL为/news/index.php?id=3,REQUEST_URI代表/news/index.php?id=3,REQUEST_FILENAME代表/news/index.php;


第二部分为请求头,图中只是一部分请求头字段,不同的请求可能包含不同的请求头字段,关于请求头的所有字段具体可参见https://baike.baidu.com/item/http%E8%AF%B7%E6%B1%82%E5%A4%B4/6623287?fr=aladdin

如果要对请求头中的数据进行分析判断,本人常用的变量如下:

REQUEST_HEADERS:代表所有请求头的集合,也可以用于检查所指定的请求头内容(通过使用REQUEST_HEADERS:Header-Name语法);

#该规则表示,如果请求头中的HOST字段的内容为IP地址的话,则使用deny动作拒绝此次访问,同时向客户端返回400错误
SecRule REQUEST_HEADERS:Host "^[\d\.]+$" "phase:1,deny,id:47,log,status:400,msg:'Host header is a numeric IP address'"


第三部分为请求体,使用POST方式提交的数据将在请求体中体现。

如果要对请求体的数据进行分析判断,首先需要将SecRequestBodyAccess指令设置为On(一般情况下默认为On),除此之外,规则的处理阶段,即phase,需要指定为2;本人常用的变量如下:

REQUEST_BODY:代表服务端接收到的原始请求体,但不包含上传文件的内容;

#该规则表示,如果请求体当中包含eval字符,则拦截此次访问
SecRule REQUEST_BODY "@containsWord eval" "phase:2,block,id:43,t:lowercase"


二、文件上传请求

下方是ModSecurity的审计日志功能记录的一次文件上传请求:

POST /upload_file.php HTTP/1.1
Host: www.modsecurity.cn
Connection: keep-alive
Content-Length: 385
Cache-Control: max-age=0
Origin: http://49.233.80.239
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarydjsVsDMzCYUlZWyn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.modsecurity.cn/upload.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

------WebKitFormBoundarydjsVsDMzCYUlZWyn
Content-Disposition: form-data; name="file"; filename="新建文本文档.txt"
Content-Type: text/plain

11111111111111111111111111111
22222222222222222222222222222
33333333333333333333333333333
------WebKitFormBoundarydjsVsDMzCYUlZWyn
Content-Disposition: form-data; name="param"

123456
------WebKitFormBoundarydjsVsDMzCYUlZWyn--


文件上传请求与普通请求的区别,除了部分请求头内容会有不同外,主要区别在于请求体:

QQ截图20191214214934.jpg

此时需要注意,REQUEST_BODY虽然代表服务端接收到的原始请求体,但却不包含上传文件的内容,即不能使用REQUEST_BODY对文件内容进行分析,而是需要使用FILES_TMP_CONTENT。本人常用的变量如下:

FILES_TMP_CONTENT:代表一个键值集,其中值是上传文件的内容,使用此变量需将SecUploadKeepFiles指令设置为RelevantOnly或On;

#该规则链表示,如果上传的文件中有小于等于50KB(51200字节)的文件,则对文件内容进行判断,如果文件中包含eval字符串,则拦截此次访问
#使用该规则链时请注意,如果一次上传多个文件,只要有一个文件满足小于等于50KB的要求,则有可能导致会对所有文件的内容进行分析
#比如一次上传两个文件,一个是30KB,而一个是100MB,有可能两个文件的内容都会被进行分析,而不是只分析小于50KB的那个文件,实际情况本人后续会进行测试
SecRule FILES_SIZES "@le 51200" "phase:2,block,id:44,chain,log"
    SecRule FILES_TMP_CONTENT "@containsWord eval" "t:lowercase"

规则链的写法教程可参见:http://www.modsecurity.cn/practice/post/7.html


MULTIPART_FILENAME:代表请求体中filename的值,即上传文件的名称;

#该规则表示,如果上传的文件是php、asp、aspx、asa、asax程序文件的话,拦截此次访问
SecRule MULTIPART_FILENAME "(?:\.php|\.asp|\.aspx|\.asa|\.asax)$" "phase:2,block,log,id:56,t:lowercase"


三、其他补充

上述变量仅为本人个人经常使用的变量,更多变量及代表的含义可参见ModSecurity中文手册:http://www.modsecurity.cn/chm/

新添加规则,或规则变更后,需要将配置文件重新加载,如Apache为:apachectl graceful、Nginx为:nginx -s reload,规则才可生效。

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。