0x01 前言
在安装完ModSecurity我发现日志里会出现Permission denied的内容,却并不影响服务的正常运行。经过多番查找,终于找到了问题点。
0x02 BUG
安装完ModSecurity后进行测试,查看日志会发现以下内容:
2017/09/07 10:45:40 [error] 8547#0: [client 10.1.1.16] ModSecurity: Audit log: Failed to unlock global mutex: Permission denied [hostname "modsecurity"] [uri "/favicon.ico"] [unique_id "7cAcAcAcAcAcAcAcAcAcAcAc"]
0x03 DEBUG
首先正常情况下的日志是这样的:
2017/09/07 11:09:57 [error] 8551#0: [client 10.1.1.16] ModSecurity: Access denied with code 403 (phase 2). Pattern match "^[\\d.:]+$" at REQUEST_HEADERS:Host. [file "/usr/local/nginx/modsecurity/owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "810"] [id "920350"] [rev "2"] [msg "Host header is a numeric IP address"] [data "10.1.1.113"] [severity "WARNING"] [ver "OWASP_CRS/3.0.0"] [maturity "9"] [accuracy "9"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [hostname "modsecurity"] [uri "/favicon.ico"] [unique_id "bcAcAcAcAcAEScIcAcAcAcAc"]
以上日志格式可以在nginx的错误日志里找到,例如我的:
[root@modsecurity 20170907]# tail -n 1 /var/log/nginx/error.log 2017/09/07 11:09:57 [error] 8551#0: [client 10.1.1.16] ModSecurity: Access denied with code 403 (phase 2). Pattern match "^[\\d.:]+$" at REQUEST_HEADERS:Host. [file "/usr/local/nginx/modsecurity/owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "810"] [id "920350"] [rev "2"] [msg "Host header is a numeric IP address"] [data "10.1.1.113"] [severity "WARNING"] [ver "OWASP_CRS/3.0.0"] [maturity "9"] [accuracy "9"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [hostname "modsecurity"] [uri "/favicon.ico"] [unique_id "bcAcAcAcAcAEScIcAcAcAcAc"]
另外在modsecurity.conf里还有一个日志路径和类型的参数:
SecAuditLogType Serial SecAuditLog /var/log/modsec_audit.log
以上解释可以在以下地址中找到:
而在modsec_audit.log文件中的日志一般是这样的:
--46e97f77-A-- [07/Sep/2017:10:45:40 +0800] 7cAcAcAcAcAcAcAcAcAcAcAc 10.1.1.16 59774 127.0.0.1 80 --46e97f77-B-- GET /favicon.ico HTTP/1.1 Host: 10.1.1.113 Connection: keep-alive Pragma: no-cache Cache-Control: no-cache User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36 Accept: image/webp,image/apng,image/*,*/*;q=0.8 Referer: http://10.1.1.113/?../../passwd Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8 --46e97f77-F-- HTTP/1.1 403 Content-Type: text/html Content-Length: 577 Connection: keep-alive --46e97f77-H-- Message: Access denied with code 403 (phase 2). Pattern match "^[\\d.:]+$" at REQUEST_HEADERS:Host. [file "/usr/local/nginx/modsecurity/owasp-modsecurity-crs/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "810"] [id "920350"] [rev "2"] [msg "Host header is a numeric IP address"] [data "10.1.1.113"] [severity "WARNING"] [ver "OWASP_CRS/3.0.0"] [maturity "9"] [accuracy "9"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] Message: Audit log: Failed to lock global mutex: Permission denied Action: Intercepted (phase 2) Apache-Handler: IIS Stopwatch: 1504752340000137 137800 (- - -) Stopwatch2: 1504752340000137 137800; combined=582, p1=192, p2=357, p3=0, p4=0, p5=33, sr=31, sw=0, l=0, gc=0 Producer: ModSecurity for nginx (STABLE)/2.9.2 (http://www.modsecurity.org/); OWASP_CRS/3.0.2. Server: ModSecurity Standalone Engine-Mode: "ENABLED" --46e97f77-Z--
问题就出在modsec_audit.log这个日志里。
你会发现除非将nginx的用户修改为root,否则哪怕将文件权限设为777也会出现这个错误。
这是因为nginx和apache都是多线程的,每条线程都需要写入日志,在这种情况下就会发生A线程打开了文件,B线程就无法打开的情况。
那么只好将错误单独写入文件,让每条线程都有权限建立文件即可。
首先需要创建一个给nginx使用的用户与用户组:
#创建用户组 [root@modsecurity ~]# groupadd nginx #创建用户 [root@modsecurity ~]# useradd -M -s /sbin/nologin -n nginx -g nginx
然后将nginx的用户修改为nginx:
user nginx;
还需要新建一个日志文件夹并赋予相关权限:
#新建文件夹 [root@modsecurity ~]# mkdir /var/log/modsecurity/ #修改所有用户与用户组 [root@modsecurity ~]# chown nginx. /var/log/modsecurity #查看相关文件夹 [root@modsecurity ~]# ll /var/log/ | grep modsecurity drwxr-xr-x 3 nginx nginx 21 Sep 7 10:41 modsecurity
最后修改modsecurity.conf文件:
#注释以下内容 #SecAuditLogType Serial #SecAuditLogStorageDir /opt/modsecurity/var/audit/ #增加以下内容 SecAuditLogType Concurrent SecAuditLogStorageDir /var/log/modsecurity
完成后reload nginx即可。
0x04 测试
完成修改并重新加载nginx后再次测试,会发现再也没有Permission denied的日志了。
而在日志目录里则会以日期为名称的文件夹,文件夹里会有以小时为名称的文件夹,文件夹下则是以事件id为名称的日志文件:
[root@modsecurity ~]# tree /var/log/modsecurity/ /var/log/modsecurity/ └── 20170907 ├── 20170907-1041 │ ├── 20170907-104154-AcACAcAcAcAcAcAcAcAcAcHc
该日志文件和modsec_audit.log日志里的格式一致。
修改完配置文件后,modsec_audit.log日志里的日志格式会发生变化,会变成非常简洁的格式:
modsecurity 10.1.1.16 - [07/Sep/2017:11:09:57 +0800] "GET /?../../passwd HTTP/1.1" 403 0 "-" "-" AcAcwcOcxcAcAcAAAqjcAcOc "-" /20170907/20170907-1109/20170907-110957-AcAcwcOcxcAcAcAAAqjcAcOc 0 1804 md5:81cbec4e20652d8948e5967b55d821d4
而nginx错误日志里的格式则保持不不变。
0x05 结语
日志记录方式SecAuditLogType修改为Concurrent还一个好处,当需要将日志存储在云端,将不需要手动将日志截断,也不需要担心日志是否正在被写入。
其实这个问题并不是造成任何影响,日志还是可以被正常记录。唯一不好的是会增加日志文件的大小。
-更新:2017-09-21
modsecurity与新版nginx不兼容的问题已在modsecurity v3中解决,请参考以下文章进行编译安装: