ModSecurity Nginx完全配置指南
安装
略过
配置
1.准备配置文件
创建/etc/modsecurity.d
目录,该目录有以下文件
-rw-r--r-- 1 root root 11K Aug 1 23:55 modsecurity.conf
-rw-r--r-- 1 root root 1.1K Aug 1 23:55 modsecurity-override.conf
drwxr-xr-x 7 root root 4.0K Aug 2 00:06 owasp-crs
-rw-r--r-- 1 root root 693 Aug 1 23:55 setup.conf
-rw-r--r-- 1 root root 52K Aug 1 23:55 unicode.mapping
unicode.mapping对应:https://github.com/SpiderLabs/ModSecurity/blob/v3/master/unicode.mapping
modsecurity.conf对应:https://github.com/SpiderLabs/ModSecurity/blob/v3/master/modsecurity.conf-recommended
setup.conf对应:https://github.com/coreruleset/modsecurity-crs-docker/blob/develop/src/etc/modsecurity.d/setup.conf
owasp-crs对应:https://github.com/coreruleset/coreruleset/releases
modsecurity-override.conf为重写一部分配置,下面的仅供参考:
modsecurity-override.conf
# Original of the latest recommended version:
# https://github.com/SpiderLabs/ModSecurity/blob/v3/master/modsecurity.conf-recommended
SecArgumentSeparator &
SecAuditEngine RelevantOnly
SecAuditLog /var/log/modsecurity/audit/modsec_audit.log
SecAuditLogFormat JSON
SecAuditLogParts ABIJDEFHZ
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogStorageDir /var/log/modsecurity/audit
SecAuditLogType Serial
SecCookieFormat 0
SecDataDir /tmp/modsecurity/data
SecDebugLog /dev/null
SecDebugLogLevel 0
SecPcreMatchLimit 100000
SecPcreMatchLimitRecursion 100000
SecRequestBodyAccess on
SecRequestBodyLimit 20971520
SecRequestBodyJsonDepthLimit 512
SecRequestBodyLimitAction Reject
SecRequestBodyNoFilesLimit 3145728
SecResponseBodyAccess on
SecResponseBodyLimit 1048576
SecResponseBodyLimitAction ProcessPartial
SecResponseBodyMimeType text/plain text/html text/xml
SecRuleEngine On
SecStatusEngine Off
SecTmpDir /tmp/modsecurity/tmp
SecTmpSaveUploadedFiles on
SecUnicodeMapFile unicode.mapping 20127
SecUploadDir /tmp/modsecurity/upload
SecUploadFileMode 0644
其中owasp-crs可以自己定义一些前置规则或者后置规则
示例:
前置规则
REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
(对应的是owasp-crs目录下的REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example)
# https://github.com/coreruleset/coreruleset/blob/v3.4/dev/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example
#
# "...,ctl:ruleRemoveById=942100"
# "...,ctl:ruleRemoveByTag=attack-sqli"
# "...,ctl:ruleRemoveTargetById=942100;ARGS:password"
# "...,ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:password"
# ------------------------------------------------------------------------
# OWASP ModSecurity Core Rule Set ver.4.0.0-rc1
# Copyright (c) 2006-2020 Trustwave and contributors. All rights reserved.
# Copyright (c) 2021-2022 Core Rule Set project. All rights reserved.
#
# The OWASP ModSecurity Core Rule Set is distributed under
# Apache Software License (ASL) version 2
# Please see the enclosed LICENSE file for full details.
# ------------------------------------------------------------------------
#
# The purpose of this file is to hold LOCAL exceptions for your site. The
# types of rules that would go into this file are one where you want to
# short-circuit inspection and allow certain transactions to pass through
# inspection or if you want to alter rules that are applied.
#
# This file is named REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example for a
# very specific reason. Files affixed with the .example extension are designed
# to contain user created/modified data. The '.example'. extension should be
# renamed to end in .conf. The advantage of this is that when OWASP CRS is
# updated, the updates will not overwrite a user generated configuration file.
#
# As a result of this design paradigm users are encouraged NOT to directly
# modify rules. Instead they should use this
# REQUEST-900-EXCLUSION-RULES-BEFORE-CRS and the
# RESPONSE-999-EXCLUSION-RULES-AFTER-CRS file to modify OWASP rules using
# methods similar to the examples specified below.
#
# REQUEST-900-EXCLUSION-RULES-BEFORE-CRS and
# RESPONSE-999-EXCLUSION-RULES-AFTER-CRS serve different purposes. ModSecurity
# effectively maintains two different context: startup, and per transaction.
# As a rule, directives are processed within the startup context. While they
# can affect the per transaction context they generally remain fixed during the
# execution of ModSecurity.
#
# As a result if one wanted to disable a rule at bootup the SecRuleRemoveById
# directive or one of its siblings would have to be placed AFTER the rule is
# listed, otherwise it will not have knowledge of the rules existence (since
# these rules are read in at the same time). This means that when using
# directives that effect SecRules, these exceptions should be placed AFTER all
# the existing rules. This is why RESPONSE-999-EXCLUSION-RULES-AFTER-CRS is
# designed such that it loads LAST.
#
# Conversely, ModSecurity supports several actions that can change the state of
# the underlying configuration during the per transaction context, this is when
# rules are being processed. Generally, these are accomplished by using the
# 'ctl' action. As these are part of a rule, they will be evaluated in the
# order rules are applied (by physical location, considering phases). As a
# result of this ordering a 'ctl' action should be placed with consideration to
# when it will be executed. This is particularly relevant for the 'ctl' options
# that involve modifying ID's (such as ruleRemoveById). In these cases it is
# important that such rules are placed BEFORE the rule ID they will affect.
# Unlike the setup context, by the time we process rules in the per-transaction
# context, we are already aware of all the rule ID's. It is by this logic that
# we include rules such as this BEFORE all the remaining rules. As a result
# REQUEST-900-EXCLUSION-RULES-BEFORE-CRS is designed to load FIRST.
#
# As a general rule:
# ctl:ruleEngine -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS
# ctl:ruleRemoveById -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS
# ctl:ruleRemoveByMsg -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS
# ctl:ruleRemoveByTag -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS
# ctl:ruleRemoveTargetById -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS
# ctl:ruleRemoveTargetByMsg -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS
# ctl:ruleRemoveTargetByTag -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS
#
# SecRuleRemoveById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS
# SecRuleRemoveByMsg -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS
# SecRuleRemoveByTag -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS
# SecRuleUpdateActionById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS
# SecRuleUpdateTargetById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS
# SecRuleUpdateTargetByMsg -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS
# SecRuleUpdateTargetByTag -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS
#
#
# What follows are a group of examples that show you how to perform rule
# exclusions.
#
#
# Example Exclusion Rule: Disable inspection for an authorized client
#
# This ruleset allows you to control how ModSecurity will handle traffic
# originating from Authorized Vulnerability Scanning (AVS) sources. See
# related blog post -
# https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/updated-advanced-topic-of-the-week-handling-authorized-scanning-traffic/
#
# Allow List ASV network block (no blocking or logging of AVS traffic) Update
# IP network block as appropriate for your AVS traffic
#
# ModSec Rule Exclusion: Disable Rule Engine for known ASV IP
# SecRule REMOTE_ADDR "@ipMatch 192.168.1.100" \
# "id:1000,\
# phase:1,\
# pass,\
# nolog,\
# ctl:ruleEngine=Off"
#
#
# Example Exclusion Rule: Removing a specific ARGS parameter from inspection
# for an individual rule
#
# This rule shows how to conditionally exclude the "password"
# parameter for rule 942100 when the REQUEST_URI is /index.php
# ModSecurity Rule Exclusion: 942100 SQL Injection Detected via libinjection
#
# SecRule REQUEST_URI "@beginsWith /index.php" \
# "id:1001,\
# phase:1,\
# pass,\
# nolog,\
# ctl:ruleRemoveTargetById=942100;ARGS:password"
#
#
# Example Exclusion Rule: Removing a specific ARGS parameter from inspection
# for only certain attacks
#
# Attack rules within the CRS are tagged, with tags such as 'attack-lfi',
# 'attack-sqli', 'attack-xss', 'attack-injection-php', et cetera.
#
# ModSecurity Rule Exclusion: Disable inspection of ARGS:pwd
# for all rules tagged attack-sqli
# SecRule REQUEST_FILENAME "@endsWith /wp-login.php" \
# "id:1002,\
# phase:2,\
# pass,\
# nolog,\
# ctl:ruleRemoveTargetByTag=attack-sqli;ARGS:pwd"
#
# Example Exclusion Rule: Removing a specific ARGS parameter from inspection
# for all CRS rules
#
# This rule illustrates that we can use tagging very effectively to allow list a
# common false positive across an entire ModSecurity instance. This can be done
# because every rule in OWASP_CRS is tagged with OWASP_CRS. This will NOT
# affect custom rules.
#
# ModSecurity Rule Exclusion: Disable inspection of ARGS:pwd
# for all CRS rules
# SecRule REQUEST_FILENAME "@endsWith /wp-login.php" \
# "id:1003,\
# phase:2,\
# pass,\
# nolog,\
# ctl:ruleRemoveTargetByTag=OWASP_CRS;ARGS:pwd"
#
# Example Exclusion Rule: Removing a range of rules
#
# This rule illustrates that we can remove a rule range via a ctl action.
# This uses the fact, that rules are grouped by topic in rule files covering
# a certain id range.
#
# ModSecurity Rule Exclusion: Disable all SQLi and XSS rules
# SecRule REQUEST_FILENAME "@beginsWith /admin" \
# "id:1004,\
# phase:2,\
# pass,\
# nolog,\
# ctl:ruleRemoveById=941000-942999"
#
#
# The application-specific rule exclusion plugins
# (see: https://github.com/coreruleset/plugin-registry)
# provide additional examples which can be useful then tuning a service.
#
# Example Rule: Allow monitoring tools and scripts
#
# Uncomment this rule to allow all requests from trusted IPs and User-Agent.
# This can be useful for monitoring tools like Monit, Nagios, or other agents.
# For example, if you're using AWS Load Balancer, you may need to trust all
# requests from "10.0.0.0/8" subnet that come with the user-agent
# "ELB-HealthChecker/2.0". By doing this, all requests that match these
# conditions will not be matched against the following rules:
#
# - id: 911100 (allowed methods)
# - id: 913100,913110,913120,913101,913102 (scan detection)
# - id: 920280 (missing/empty host header)
# - id: 920350 (IP address in host header)
# - tag: attack-disclosure (all RESPONSE-*-DATA-LEAKAGES rules)
#
# SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8" \
# "id:1005,\
# phase:1,\
# pass,\
# nolog,\
# chain"
# SecRule REQUEST_METHOD "@pm GET HEAD" "chain"
# SecRule REQUEST_HEADERS:User-Agent "@pm ELB-HealthChecker" \
# "ctl:ruleRemoveById=911100,\
# ctl:ruleRemoveById=913100,\
# ctl:ruleRemoveById=913110,\
# ctl:ruleRemoveById=913120,\
# ctl:ruleRemoveById=913101,\
# ctl:ruleRemoveById=913102,\
# ctl:ruleRemoveById=920280,\
# ctl:ruleRemoveById=920350,\
# ctl:ruleRemoveByTag=attack-disclosure"
# 解决base64被拦截
SecRule ARGS:json.photo "@beginsWith data:image/jpeg;base64," \
"id:1001,\
phase:2,\
pass,\
nolog,\
ctl:ruleEngine=Off"
# ip黑名单
# SecRule REMOTE_ADDR "@ipMatchFromFile /etc/modsecurity.d/ips/ips.txt" "id:1002,phase:2,deny,log,auditlog"
后置规则
RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
(对应的是owasp-crs目录下的RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example)
# https://github.com/coreruleset/coreruleset/blob/v3.4/dev/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example
#
# Examples:
# SecRuleRemoveById 942100
# SecRuleRemoveByTag "attack-sqli"
# SecRuleUpdateTargetById 942100 "!ARGS:password"
# SecRuleUpdateTargetByTag "attack-sqli" "!ARGS:password"
# 排除此条规则(US-ASCII encoding bypass listed on XSS filter evasion)
SecRuleRemoveById 941310
# 排除此条规则 Invalid character in request (null character)
SecRuleRemoveById 920270
SecRuleRemoveById 942100
SecRuleRemoveById 942100
2.创建ModSecurity需要的文件夹
创建目录
配置文件的所有文件夹,ModSecurity不会自动创建,因此需要手动创建,并赋予Nginx写入的权限
mkdir -p /var/log/modsecurity/audit/
mkdir -p /tmp/modsecurity/data
mkdir -p /tmp/modsecurity/tmp
mkdir -p /tmp/modsecurity/upload
赋予权限
3.启用ModSecurity
创建/usr/local/nginx/conf/modsecurity.conf
文件,内容如下
modsecurity on;
modsecurity_rules_file /etc/modsecurity.d/setup.conf;
编辑/usr/local/nginx/conf/nginx.conf
文件
在末尾加入如下一行:
include modsecurity.conf;
重启Nginx
service nginx restart
查看是否生效
curl localhost/index.html?exec=/bin/bash
如果是403且审计日志有对应的日志,则说明已经生效
参考
https://github.com/SpiderLabs/ModSecurity
https://github.com/coreruleset/coreruleset
https://github.com/coreruleset/modsecurity-crs-docker
https://owasp.org/www-project-modsecurity-core-rule-set/
https://www.netnea.com/cms/apache-tutorial-7_including-modsecurity-core-rules/