ModSecurity 3.x

最後更新: 2021-07-21

介紹

 

ModSecurity 3.x

It is no longer just a module !

Nginx-connector -> Libmodsecurity

Link: https://github.com/SpiderLabs/ModSecurity
Link: https://github.com/SpiderLabs/ModSecurity-nginx
Link: https://github.com/libinjection/libinjection

 


Complie libModSecurity

 

# Centos 7

# 準備

yum groupinstall 'Development Tools' -y
yum install gcc-c++ flex bison yajl yajl-devel curl-devel curl GeoIP-devel zlib-devel
yum install lmdb lmdb-devel libxml2 libxml2-devel ssdeep ssdeep-devel lua lua-devel

# Get Source

mkdir /usr/src/libmodsecurity; cd /usr/src/libmodsecurity
wget https://github.com/SpiderLabs/ModSecurity/archive/refs/tags/v3.0.5.zip \
 -O libmodsecurity_v3.0.5.zip
wget https://github.com/libinjection/libinjection/archive/refs/tags/v3.9.2.zip \
 -O libinjection_v3.9.2.zip
unzip libmodsecurity_v3.0.5.zip
unzip libinjection_v3.9.2.zip
mv libinjection-3.9.2 ModSecurity-3.0.5/others/libinjection

cd ModSecurity-3.0.5

export CFLAGS="-O3"

./build.sh                       # ignore any fatal

./configure --prefix=/opt/modsecurity \
  --disable-doxygen-doc --disable-static

make -j 2                        # 要有 2G ram 才 build 到

make install

 


Nginx Connector

 

# Get Source

mkdir /usr/src/ModSecurity-nginx

cd /usr/src/ModSecurity-nginx

wget https://github.com/SpiderLabs/ModSecurity-nginx/archive/refs/tags/v1.0.2... \
  -O ModSecurity-nginx_v1.0.2.zip

unzip ModSecurity-nginx_v1.0.2.zip

VER=nginx-1.19.10

mkdir /usr/src/nginx

cd /usr/src/nginx

wget http://nginx.org/download/${VER}.tar.gz

tar -zxf ${VER}.tar.gz

# Config

export MODSECURITY_INC="/opt/modsecurity/include/"

export MODSECURITY_LIB="/opt/modsecurity/lib/"

useradd nginx -s /bin/nologin --home /var/spool/nginx -m

cd ${VER}

./configure \
 --with-cc-opt='-O3' \
 --prefix=/opt/nginx \
 --user=nginx --group=nginx \
 --conf-path=/etc/nginx/nginx.conf \
 --error-log-path=/var/log/nginx/error.log \
 --http-log-path=/var/log/nginx/access.log  \
 --lock-path=/var/lock/subsys/nginx \
 --pid-path=/var/run/nginx.pid \
 --http-client-body-temp-path=/var/spool/nginx/client_body_temp \
 --http-proxy-temp-path=/var/spool/nginx/proxy_temp \
 --with-pcre-jit --with-http_realip_module \
 --with-http_ssl_module --with-threads \
 --with-http_stub_status_module \
 --with-compat \
 --add-dynamic-module=/usr/src/ModSecurity-nginx/ModSecurity-nginx-1.0.2

# 全部建立

make                # 別加 "-j" 否則會不夠 RAM

make install

# 只建立 modules 情況

make modules

mkdir -p /var/log/nginx \
/var/spool/nginx/client_body_temp \
/var/spool/nginx/proxy_temp

chown nginx:nginx /var/log/nginx \
/var/spool/nginx/client_body_temp \
/var/spool/nginx/proxy_temp

ln -s /opt/nginx/sbin/nginx /usr/sbin

# modules

cp objs/ngx_http_modsecurity_module.so /opt/nginx/modules

mkdir /etc/nginx/modsec

cp ~/ModSecurity/unicode.mapping /etc/nginx/modsec/

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

 


Nginx Config

 

/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 52
    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 Setting

 

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-available/proxy_www.conf

upstream MyBackend {
    ip_hash;
    server 192.168.123.11:80 max_conns=10;
    keepalive 10;
    keepalive_requests 3000;
    keepalive_timeout 100;
    zone myweb 128k;
}

server {
    listen 80;
    server_name     datahunter.org www.datahunter.org;
    root /var/www/html;
    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;

    modsecurity on;
    modsecurity_transaction_id "$request_id";

    access_log /var/log/nginx/waf.datahunter.org-access.log extended;
    error_log  /var/log/nginx/waf.datahunter.org-error.log;
    location = /40x.html {
        root /var/www/html;
        modsecurity on;
        internal;
    }
    location / {
        # 要 full path
        modsecurity_rules_file /etc/nginx/modsecurity.rules;
    }
}

modsecurity.rules

SecRuleEngine On;
SecDebugLog /var/log/nginx/waf.datahunter.org-modsec_debug.log;

# 0~9
#SecDebugLogLevel 9;

# bypass some rule
#SecRuleRemoveById 10

modsecurity

# context: http, server, location

# Turns on ModSecurity functionality

modsecurity_rules_file

# context: http, server, location

# The location of the modsecurity configuration

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

recommended setting

ModSecurity-3.0.5/modsecurity.conf-recommended

測試

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)

加入 ModSecurity Setting

mkdir /etc/nginx/owasp-modsecurity-crs

cp -a crs-setup.conf.example /etc/nginx/owasp-modsecurity-crs/crs-setup.conf

cp -a rules /etc/nginx/owasp-modsecurity-crs

modsecurity.rules

# CRS Setting
include owasp-modsecurity-crs/crs-setup.conf
include owasp-modsecurity-crs/rules/*.conf

Test

http://localhost/?param="><script>alert(1);</script>

waf.datahunter.org-access.log

... 403 ... ID

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-(v2.x)