本文将对服务器端接收的数据格式进行分析,以此为出发点来介绍如何编写ModSecurity规则。
ModSecurity官方免费规则可点击此处下载。
ModSecurity是对WEB服务端收到的访问数据,以及WEB服务端发送至客户端的数据进行分析判断来进行安全防护,因此我们要了解WEB服务器端接收到的数据格式,ModSecurity的每个变量所对应的是哪部分的数据,以及如何利用ModSecurity对指定的数据进行判断来确定是否拦截。
一、普通请求
WEB请求发送至服务端的数据分为三部分,请求行、请求头、请求体。下方是一次普通WEB请求发送的数据格式:
第一部分为请求行,请求行又包含三个部分:
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--
文件上传请求与普通请求的区别,除了部分请求头内容会有不同外,主要区别在于请求体:
此时需要注意,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://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,规则才可生效。
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。