最後更新: 2022-11-30
介紹
mod_security =WAF - application firewall
HomePage: http://www.modsecurity.org/documentation/
功能
- 抵擋 SQL injection attacks, cross-site scripting, path traversal attacks
- HTTP Denial of Service Protections
- Detecting common web application security attack
- Integration with AV Scanning for File Uploads
- Tracking Sensitive Data - Tracks Credit Card usage and blocks leakages
- Identification of Application Defects
目錄
- Installation
- Basic Configure
- Disable "mod_security" Per Folder
- More Setting
- Rule 入門 - SecRule
- mod_unique_id
- Install Core ModSecurity Rule Set ver.2.2.9
- Doc
與 mod_rewrite 比較
modsecurity 可以處理 POST
modsecurity response 內容 (server output)
modsecurity 支援 Block Brute-Froce Attacks
Notes
mod_rewrite will not work on POST parameters.
原因: the parameters of a POST request are found within the request body
GET 情況用 "QUERY_STRING"
Installation
C6 /C7
yum install mod_security
Module
C7
/etc/httpd/conf.modules.d/10-mod_security.conf
LoadModule security2_module modules/mod_security2.so <IfModule !mod_unique_id.c> LoadModule unique_id_module modules/mod_unique_id.so </IfModule>
* Make sure you have mod_unique_id installed. mod_unique_id is packaged with Apache httpd.
/etc/httpd/conf.d/mod_security.conf
... Include modsecurity.d/*.conf Include modsecurity.d/activated_rules/*.conf ...
Basic Settings
/etc/httpd/conf.d/mod_security.conf
<IfModule mod_security2.c> SecRuleEngine DetectionOnly SecRequestBodyAccess Off SecResponseBodyAccess Off SecPcreMatchLimit 1000 SecPcreMatchLimitRecursion 1000 SecTmpDir /var/lib/mod_security SecDataDir /var/lib/mod_security </IfModule>
DetectionOnly(log only)
# Settings: on / off / DetectionOnly
SecRuleEngine DetectionOnly
SecPcreMatchLimit 1500 # Default
Description: Sets the match limit in the PCRE library.
SecPcreMatchLimitRecursion 1500 # Default
Description: Sets the match limit recursion in the PCRE library.
SecTmpDir /var/lib/mod_security
As of ModSecurity version 3.0, SecTmpDir is no longer supported.
libModSecurity is able to deal with request body in a file or in a buffer (chunked or not).
(e.g. nginx 's client_body_buffer_size)
Supported on libModSecurity: No
SecDataDir /var/lib/mod_security
Description: Path where persistent data (e.g., IP address data, session data, and so on) is to be stored.
The directory to which the directive points must be writable by the web server user.
Supported on libModSecurity: No
Default Action
當中 rule 時出 HttpStatusCode 417
SecDefaultAction "phase:1,nolog,auditlog,deny,status:417" SecDefaultAction "phase:2,nolog,auditlog,deny,status:417" SecDefaultAction "phase:3,nolog,auditlog,deny,status:417" SecDefaultAction "phase:4,nolog,auditlog,deny,status:417"
* status 不可以撞 nginx 內置那些, 比如 444, 499
Remark: log 的組合
- nolog,noauditlog
- log,auditlog
Bodiy Check
Whether request bodies will be buffered and processed by ModSecurity
SecRequestBodyAccess Off
Whether response bodies are to be buffered
# This is only neccessary if data leakage detection and protection is required.
SecResponseBodyAccess Off
* 改完 settings / rules 要 service httpd reload
Disable "mod_security" Per Folder
SecRuleEngine, SecRequestBodyAccess, SecRule
Scope: Any
# For a particular directory:
<Directory "/var/www/wp-admin">
<IfModule security2_module>
SecRuleEngine Off
</IfModule>
</Directory>
OR
# Remove a particular rule
<LocationMatch "/wp-admin/update.php">
<IfModule security2_module>
SecRuleRemoveById 981173
</IfModule>
</LocationMatch>
More Setting
Body(Request)
# Configures whether request bodies will be buffered and processed by ModSecurity(POST data)
SecRequestBodyAccess On
# 當 POST 的 size 超過 SecRequestBodyLimit 時如何處理
SecRequestBodyLimitAction Reject
# Configures the maximum request body size that ModSecurity will store in memory.
# When a multipart/form-data request is being processed, once the in-memory limit is reached,
# the request body will start to be streamed into a temporary file on disk.
SecRequestBodyInMemoryLimit 131072
# file uploads. "413 Request Entity Too Large error"
SecRequestBodyLimit 15728640
# limits the size of POST data (不是 upload file 的 data)
SecRequestBodyNoFilesLimit 131072
# Enable XML request body parser.
# Initiate XML Processor in case of xml content-type
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \ "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
# Enable JSON request body parser.
# Initiate JSON Processor in case of JSON content-type; change accordingly
# if your application does not use 'application/json'
#
SecRule REQUEST_HEADERS:Content-Type "application/json" \ "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
# As a rule of thumb, when failing to process a request body
# you should reject the request (when deployed in blocking mode)
# or log a high-severity alert (when deployed in detection-only mode).
SecRule REQBODY_ERROR "!@eq 0" \ "id:'200002', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"
File uploads
The location where ModSecurity stores intercepted uploaded files
SecUploadDir /opt/modsecurity/var/upload
# allow group access the file
SecUploadFileMode 0660
# By default, only keep the files that were determined to be unusual in some way
#SecUploadKeepFiles RelevantOnly
Body(Response)
SecResponseBodyAccess Off
PCRE library
# Sets the match limit in the PCRE library.
SecPcreMatchLimit 1000 SecPcreMatchLimitRecursion 1000
Debug
log location
SecDebugLog /var/log/httpd/modsec_debug.log
log level
# 1–3 are always copied to the Apache error log.
# 4: details of how transactions are handled
SecDebugLogLevel 0
AuditLog
SecAuditEngine
# On / Off / RelevantOnly
# For every transaction that’s blocked, ModSecurity provides detailed logs about the transaction and why it was blocked.
# RelevantOnly: only the log transactions that have triggered a warning or an error
# or have a status code that matches what’s in the SecAuditLogRelevantStatus directive.
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus
# Configures which response status code is to be considered relevant for the purpose of audit logging.
# Must have SecAuditEngine set to RelevantOnly.
# The example provided would log all 5xx and 4xx level status codes, except for 404s.
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogType
# Serial: Audit log entries will be stored in a single file
# Concurrent: One file per transaction is used for audit logging
SecAuditLogType Serial
SecAuditLogParts
# Defines which parts of each transaction are going to be recorded in the audit log
SecAuditLogParts AHZ
- A Audit log header (mandatory)
- B Request headers
- C Request body
- D Reserved
- E Response body
- F Response headers
- G Reserved
- H Audit log trailer, which contains additional data # 中了那 Rule
- I Compact request body alternative (to part C), which excludes files
- J Information on uploaded files
- K Contains a list of all rules that matched for the transaction
- Z Final boundary (mandatory)
Audit log file location
SecAuditLog /var/log/httpd/modsec_audit.log
Miscellaneous
# The location specified needs to be writable by the Apache user process.
# for stores temporary files
SecTmpDir /var/lib/mod_security
# Path where persistent data (e.g., IP address data, session data, and so on)
SecDataDir /var/lib/mod_security
# character to use as the separator for application/x-www-form- urlencoded content.
SecArgumentSeparator &
mod_unique_id
UNIQUE_ID is set to the identifier for each request.
This module provides a magic token for each request which is guaranteed to be unique across "all" requests under very specific conditions.
The UNIQUE_ID environment variable is constructed by
encoding the 144-bit (32-bit IP address, 32 bit pid, 32 bit time stamp, 16 bit counter, 32 bit thread index)
quadruple using the alphabet [A-Za-z0-9@-] in a manner similar to MIME base64 encoding, producing 24 characters.
Install Core ModSecurity Rule Set ver.2.2.9
Core Rule Set (CRS)
License: ASLv2
https://github.com/coreruleset/coreruleset
A set of generic attack detection rules for use with ModSecurity
Prepare
mkdir /usr/src/coreruleset; cd /usr/src/coreruleset
wget https://github.com/coreruleset/coreruleset/archive/refs/tags/v3.3.2.zip
unzip v3.3.2.zip
cd coreruleset-3.3.2
Install
由於 /etc/httpd/conf.d/mod_security.conf 有以下設定
<IfModule mod_security2.c> # ModSecurity Core Rules Set configuration Include modsecurity.d/*.conf Include modsecurity.d/activated_rules/*.conf
所以我們 copy 相應的 file 到指定目錄即可
cp modsecurity_crs_10_setup.conf.example /etc/httpd/modsecurity.d/modsecurity_crs_10_setup.conf
for f in `ls base_rules/` ; do cp base_rules/$f /etc/httpd/modsecurity.d/activated_rules/$f ; done
apache error log
... [notice] ModSecurity for Apache/2.7.3 (http://www.modsecurity.org/) configured. ... [notice] ModSecurity: APR compiled version="1.3.9"; loaded version="1.3.9" ... [notice] ModSecurity: PCRE compiled version="7.8 "; loaded version="7.8 2008-09-05" ... [notice] ModSecurity: LUA compiled version="Lua 5.1" ... [notice] ModSecurity: LIBXML compiled version="2.7.6"
Default Setting
SecRuleEngine On
# - To log to both the Apache error_log and ModSecurity audit_log file use: "log"
# - To log *only* to the ModSecurity audit_log file use: "nolog,auditlog"
# - To log *only* to the Apache error_log file use: "log,noauditlog"
SecDefaultAction "phase:1,deny,log" SecDefaultAction "phase:2,deny,log"
The 49 inbound blocking and 59 outbound blocking rules files use the "block" action
For test
SecDefaultAction "phase:1,pass" SecDefaultAction "phase:2,pass"
測試
/home/vhosts/MYDOMAIN/web/test.php
<?php $content = file_get_contents($_GET['path']); echo nl2br($content); ?>
http://MYDOMAIN/test.php?path=../../../../etc/passwd
Log
# 960017
[Thu Sep 17 16:36:32 2015] [error] [client 192.168.88.177] ModSecurity: Access denied with code 403 (phase 2). Pattern match "^[\\\\d.:]+$" at REQUEST_HEADERS:Host. [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_21_protocol_anomalies.conf"] [line "98"] [id "960017"] [rev "2"] [msg "Host header is a numeric IP address"] [data "192.168.88.183"] [severity "WARNING"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "9"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [tag "http://technet.microsoft.com/en-us/magazine/2005.01.hackerbasher.aspx"] [hostname "192.168.88.183"] [uri "/test.php"] [unique_id "Vfp7kMCoWLcAAAYuBhQAAAAD"]
# 960024
[Thu Sep 17 16:44:19 2015] [error] [client 192.168.88.177] ModSecurity: Access denied with code 403 (phase 2). Pattern match "\\\\W{4,}" at ARGS:path. [file "/etc/httpd/modsecurity.d/activated_rules/modsecurity_crs_40_generic_attacks.conf"] [line "37"] [id "960024"] [rev "2"] [msg "Meta-Character Anomaly Detection Alert - Repetative Non-Word Characters"] [data "Matched Data: ../../../../ found within ARGS:path: ../../../../etc/passwd"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "8"] [hostname "test.loc"] [uri "/"] [unique_id "Vfp9Y8CoWLcAAAZMA5gAAAAH"]
多個 Vhosts Settings
SecWebAppId # Default: default
Creates an application namespace, allowing for separate persistent session and user storage.
If it isn’t used, a collision between session IDs might occur.
<VirtualHost *:80> ServerName app1.example.com SecWebAppId "App1" ... </virtualhost> <VirtualHost *:80> ServerName app2.example.com SecWebAppId "App2" ... </virtualhost>
SecConnEngine
"SecConnEngine" directive affect the directives: SecConnReadStateLimit and SecConnWriteStateLimit.
Apache to switches state to SERVER_BUSY_WRITE once request headers have been read.
As an alternative, consider mod_reqtimeout
SecReadStateLimit / SecConnReadStateLimit
Establishes a per-IP address limit of how many connections are allowed to be in SERVER_BUSY_READ state.
SecConnReadStateLimit 50 "!@ipMatch 127.0.0.1"
SecWriteStateLimit / SecConnWriteStateLimit
Establishes a per-IP address limit of how many connections are allowed to be in SERVER_BUSY_WRITE state.
SecConnWriteStateLimit 50 "!@ipMatch 127.0.0.1"
SecRemoteRules
Load rules from a given file hosted on a HTTPS site.
i.e.
SecRemoteRules some-key https://www.yourserver.com/plain-text-rules.txt
SecRemoteRulesFailAction Abort|Warn # Default: Abort
Action that will be taken if SecRemoteRules specify an URL that ModSecurity was not able to download.
Doc
https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual
https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)-(Split)