最後更新: 2022-12-16
介紹
ModSecurity 3.x is no longer just a module !!
新模式:
Nginx(Nginx-connector) -> Libmodsecurity
- Libmodsecurity: https://github.com/SpiderLabs/ModSecurity
- Nginx-connector: https://github.com/SpiderLabs/ModSecurity-nginx
目錄
- Complie libModSecurity
-
Nginx Connector
Dynamic Module
Static Link - Nginx Service & Log
-
Nginx Settings
1) 原先設定好 Proxy
2) 加入 ModSecurity Setting - Clear Software Version
- 加入 OWASP CRS Rules
- Doc
Complie libModSecurity
OS: Centos 7
# 準備 Libary
yum groupinstall 'Development Tools' -y
yum install gcc-c++ flex bison yajl yajl-devel curl-devel curl GeoIP-devel zlib-devel
yum install ssdeep ssdeep-devel
yum install libxml2 libxml2-devel
yum install lmdb lmdb-devel
yum install lua lua-devel
yum install pcre2 pcre2-devel
# 準備 modsecurity
VER=3.0.8
mkdir /usr/src/modsecurity; cd /usr/src/modsecurity
# https://github.com/SpiderLabs/ModSecurity/releases
wget https://github.com/SpiderLabs/ModSecurity/releases/download/v${VER}/modsecurity-v${VER}.tar.gz
tar -zxf modsecurity-v${VER}.tar.gz
P.S.
libInjection 已經在 modsecurity source code 內, 不用再 Download
cd modsecurity-v${VER}
./configure --prefix=/opt/modsecurity \ --disable-doxygen-doc \ --with-pcre2 --with-lmdb
make -j 2 # 要有 2G ram 才 build 到
make install
du -sh /opt/modsecurity
214M /opt/modsecurity
du -sh /opt/modsecurity/lib/*
166M /opt/modsecurity/lib/libmodsecurity.a 47M /opt/modsecurity/lib/libmodsecurity.so.3.0.8
Nginx Connector
它提供了
- modsecurity on | off
- modsecurity_rules_file <path to rules file>
- modsecurity_rules_remote <key> <URL to rules>
- modsecurity_rules <modsecurity rule>
- modsecurity_transaction_id string
安裝方式
- Dynamic Module
- Static Link
Get connector source
cd /usr/src/modsecurity
# https://github.com/SpiderLabs/ModSecurity-nginx/releases
wget https://github.com/SpiderLabs/ModSecurity-nginx/releases/download/v1.0.3...
tar -zxf modsecurity-nginx-*.tar.gz
Get nginx source
nginx -v # 查看當前 nginx 的 version
nginx version: nginx/1.22.1
NGINX=nginx-1.22.1
mkdir /usr/src/nginx; cd $_
wget http://nginx.org/download/${NGINX}.tar.gz
tar -zxf ${NGINX}.tar.gz
export MODSECURITY_INC="/opt/modsecurity/include/"
export MODSECURITY_LIB="/opt/modsecurity/lib/"
cd ${NGINX}
Configure source
nginx -V |& grep 'configure arguments' > build.sh
# 修改 build.sh 移除不使用的 Module
--with-http_dav_module --with-http_random_index_module --with-http_mp4_module --with-http_flv_module --with-http_slice_module ---- --with-mail --with-mail_ssl_module ---- --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module
- As a dynamic module
- As a static module
As a dynamic module
./configure ... \ --add-dynamic-module=/usr/src/modsecurity/modsecurity-nginx-v1.0.3 --with-compat
bash build.sh
make modules
ls -lh objs/ngx_http_modsecurity_module.so
-rwxr-xr-x 1 root root 379K Dec 6 11:39 objs/ngx_http_modsecurity_module.so
# 安裝 Module
cp $_ /etc/nginx/modules
nginx.conf
load_module modules/ngx_http_modsecurity_module.so;
As a static module
./configure ... \ --add-module=/usr/src/modsecurity/modsecurity-nginx-v1.0.3
bash build.sh
make # 別加 "-j" 否則會不夠 RAM
make install
建立 nginx 帳戶
useradd nginx -s /bin/nologin --home /var/spool/nginx -m
取代現有 nginx binary
mv /usr/sbin/nginx /usr/sbin/nginx.orig
cp objs/nginx /usr/sbin/
service nginx restart
ldd /usr/sbin/nginx | grep modsecurity
libmodsecurity.so.3 => /opt/modsecurity/lib/libmodsecurity.so.3 (0x00007fe701a6f000)
Remark
- --with-compat # dynamic modules compatibility
- --with-threads # enable thread pool support
- --with-pcre-jit
- --with-pcre=../pcre-8.44
- --with-zlib=../zlib-1.2.11
- --with-openssl=../openssl-1.1.1g
- --with-openssl-opt=no-nextprotoneg
# PCRE version 8.44
wget https://ftp.pcre.org/pub/pcre/pcre-8.44.tar.gz && tar xzvf pcre-8.44.tar.gz
# zlib version 1.2.11
wget https://www.zlib.net/zlib-1.2.11.tar.gz && tar xzvf zlib-1.2.11.tar.gz
# OpenSSL version 1.1.1g
wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz && tar xzvf openssl-1.1.1g.tar.gz
unicode.mapping
mkdir /etc/nginx/modsec
cp /usr/src/modsecurity/modsecurity-v3.0.8/unicode.mapping $_
Nginx Service & Log
/etc/systemd/system/nginx.service
[Unit] Description=nginx - high performance web server After=network-online.target remote-fs.target nss-lookup.target Wants=network-online.target [Service] Type=forking PIDFile=/var/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID [Install] WantedBy=multi-user.target
/etc/logrotate.d/nginx
/var/log/nginx/*.log { daily missingok rotate 30 compress delaycompress notifempty create 640 nginx adm sharedscripts postrotate if [ -f /var/run/nginx.pid ]; then kill -USR1 `cat /var/run/nginx.pid` fi endscript }
Nginx Settings
1) 原先設定好 Proxy
nginx.conf
http { ... server_names_hash_bucket_size 64; include conf.d/*.conf; include sites-enabled/*.conf; }
/etc/nginx/proxy_params
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; add_header X-Cache-Status $upstream_cache_status;
sites-enabled/proxy_www.conf
# Backend setting upstream MyBackend { ip_hash; server 192.168.123.11:80 max_conns=32; keepalive 10; keepalive_requests 3000; keepalive_timeout 100; zone myweb 128k; } # Frontend setting server { listen 80; server_name datahunter.org www.datahunter.org; root /var/www/html; # Location Settings location ~ /\. { deny all; } location / { # ACL deny 123.123.123.123; # maintenance try_files /maintenance.html @proxy; } location @proxy { # Proxy Setting include /etc/nginx/proxy_params; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://MyBackend; } }
2) 加入 ModSecurity Setting
nginx.conf
load_module /opt/nginx/modules/ngx_http_modsecurity_module.so;
sites-available/proxy_www.conf
log_format extended '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" $request_id'; server { listen 80; server_name waf.datahunter.org; # 不開 Folder 放 log, 可不用更新 logrotate 設定 access_log /var/log/nginx/waf.datahunter.org-access.log extended; error_log /var/log/nginx/waf.datahunter.org-error.log; # Global 啟用 modsecurity modsecurity on; # 必須要 full path modsecurity_rules_file /etc/nginx/modsec/modsecurity.rules; modsecurity_transaction_id "$request_id"; # 用來放 Error Page location = /40x.html { root /var/www/html; # 個別停用 modsecurity off; internal; } location ~* \.(bmp|jpg|jpeg|png|svg|ico|gif|mp4|css|js|html|txt|woff2|zip|rar)$ { ... } location / { ... } }
說明
modsecurity
# context: http, server, location
# Turns on ModSecurity functionality
modsecurity_rules_file
# context: http, server, location
# The location of the modsecurity configuration
Nginx only supports one 'ModSecurityConfig' directive
=> multiple 'Include' directive within your 'ModSecurityConfig'
modsecurity_transaction_id string
# context: http, server, location
# Allows to pass transaction ID from nginx instead of generating it in the library.
# you will be able to find correlations between access log and error log entries using the same unique identificator
modsecurity.rules
# bypass some rule #SecRuleRemoveById 10
測試
systemctl restart nginx
/var/log/nginx/error.log
... [notice] 19874#19874: ModSecurity-nginx v1.0.2 (rules loaded inline/local/remote: 0/903/0) ... [notice] 19876#19876: ModSecurity-nginx v1.0.2 (rules loaded inline/local/remote: 0/903/0)
設定 TMP Folder
mkdir /var/lib/nginx/tmp/modsecurity /var/lib/nginx/modsecurity
chown nginx: /var/lib/nginx/tmp/modsecurity /var/lib/nginx/modsecurity
chmod 700 /var/lib/nginx/tmp/modsecurity /var/lib/nginx/modsecurity
modsecurity.rules
SecRuleEngine On SecTmpDir "/var/lib/nginx/tmp/modsecurity/" SecDataDir "/var/lib/nginx/modsecurity/"
Debug
SecRuleEngine On; SecDebugLog /var/log/nginx/modsec_debug.log; SecDebugLogLevel 5;
- 0: no logging
- 1: errors (intercepted requests) only
- 2: warnings
- 3: notices
- 4: details of how transactions are handled
- 5: as above, but including information about each piece of information handled
- 9: log everything, including very detailed debugging information
Clear Software Version
sites-enabled/proxy_www.conf
server { ... # header setting more_clear_headers 'Server'; more_clear_headers 'X-Powered-By'; }
加入 OWASP CRS Rules
Info: owasp_crs
Download
mkdir /usr/src/owasp-modsecurity-crs; cd $_
# https://github.com/coreruleset/coreruleset/releases
wget https://github.com/coreruleset/coreruleset/archive/v3.3.4.tar.gz
Install
tar -zxf v3.3.4.tar.gz
mv coreruleset-3.3.4 /usr/share
ln -s /usr/share/coreruleset-3.3.4 /usr/share/coreruleset
cp /usr/share/coreruleset/crs-setup.conf.example /usr/share/coreruleset/crs-setup.conf
location / { modsecurity_rules_file /etc/nginx/modsec/modsecurity.rules; }
modsecurity.rules
#### CRS Setting include /usr/share/coreruleset/crs-setup.conf include /usr/share/coreruleset/rules/REQUEST-*.conf #include /usr/share/coreruleset/rules/RESPONSE-*.conf
Test
http://localhost/?param="><script>alert(1);</script>
[1] waf.datahunter.org-access.log
... 403 ... ID
[2] grep ID waf.datahunter.org-error.log
... Matched "Operator `Ge' with parameter `5' against variable `TX:ANOMALY_SCORE' (Value: `15' )
Doc
- https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v3.x)
- https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)