CentOS Strem9サーバーに、Nginx+NaxsiでWAFを構築する。
(Naxsi) https://github.com/nbs-system/naxsi
1.Nginxインストール
Naxsiモジュールをコンパイルするので、Nginxもソースからインストールしたものを使うほうがいいかもしれないが、保守を考えてdnfにてインストール。
dnf install nginx
今回入れたのは、バージョン1.20.1。
2.Naxsiモジュール作成
Naxsiインストールについては、GitHubの以下にある。
https://github.com/nbs-system/naxsi/wiki/naxsi-compile#build-naxsi-as-a-dynamic-extension-for-nginx-from-your-distribution-package-ie-ubuntu
この手順に従って行えばいい。
2.1 コンパイル環境
とりあえず開発用一式を入れる。
dnf groupinstall 'Development Tools'
追加でインストールしたコマンドは以下。
dnf install gd-devel
dnf install libxslt-devel
dnf install perl-ExtUtils-Embed
2.2 Naxsiソース取得
最新のバージョンを確認して、環境変数を設定。現時点では1.3。
以下のようにして、ソースを取得して展開。
export NAXSI_VER=1.3
wget https://github.com/nbs-system/naxsi/archive/$NAXSI_VER.tar.gz -O naxsi_$NAXSI_VER.tar.gz
tar vxf naxsi_$NAXSI_VER.tar.gz
※(2023/1/25) 最新のソースは、GitHubから取得したほうがいい。コメント参照
2.3 Nginxソース取得
以下のようにして、1.20.1のソースを取得して展開。
export NGINX_VER=1.20.1
wget https://nginx.org/download/nginx-$NGINX_VER.tar.gz
tar vxf nginx-$NGINX_VER.tar.gz
2.4 Naxsi動的ライブラリの作成
dnfでインストールしたNginxと同じ設定でコンパイルする必要があるので、まずNginxの情報を取得する。
nginx -V
このコマンドの出力結果の中のconfigure argumentsを指定してconfigureを行い、モジュールのコンパイルを実行。
cd nginx-$NGINX_VER
./configure (※ここにconfigure arguments) --add-dynamic-module=../naxsi-$NAXSI_VER/naxsi_src/
make modules
今回の場合のconfigureコマンドは、具体的には以下のようになる。
./configure --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-compat --with-debug --with-file-aio --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_degradation_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-cc-opt='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -march=x86-64-v2 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --with-ld-opt='-Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -Wl,-E' --add-dynamic-module=../naxsi-$NAXSI_VER/naxsi_src/
まあNaxsiのライブラリを作りたいだけなので全部は必要ないかもしれないが、元ドキュメントに”This will ensure module will be compatible with your nginx and will load properly.”とあるように、実運用するシステムであれば、このように同じ条件でNaxsi動的ライブラリを作成するほうが安全で安心かと思う。
3.基本設定
3.1 モジュールの配置
動的ライブラリを適当な場所(/etc/nginx/moduls等)に配置する。
mkdir /etc/nginx/modules
cp objs/ngx_http_naxsi_module.so /etc/nginx/modules/
基本的なルールも、そのまま使うのでコピーする。
cp (naxsiソースディレクトリ)/naxsi_config/naxsi_core.rules /etc/nginx/
3.2 Nginxの設定
/etc/nginx/nginx.confに、モジュールとルールの読み込みと、Naxsiの設定を以下の例を参考に追加していく。
...
load_module /etc/nginx/modules/ngx_http_naxsi_module.so; # naxsiのロード
http {
include /etc/nginx/naxsi_core.rules; # naxsi基本ルールのロード
...
}
...
server {
...
location / { # naxsi is enabled, and in learning mode
SecRulesEnabled; # naxsiを有効に
LearningMode; #学習モードを有効に ※エラーページにしたい場合はこれを外す
LibInjectionSql; #SQLインジェクションへのサポートを有効に
LibInjectionXss; #XSSインジェクションへのサポートを有効に
DeniedUrl "/RequestDenied"; #naxsiがブロックした場合のリダイレクト先
CheckRule "$SQL >= 8" BLOCK; #$SQLにスコアが8以上になった場合のアクションがBLOCK
CheckRule "$RFI >= 8" BLOCK;
CheckRule "$TRAVERSAL >= 5" BLOCK;
CheckRule "$UPLOAD >= 5" BLOCK;
CheckRule "$XSS >= 8" BLOCK;
proxy_pass http://10.10.10.1; # WAFを設定したいWebサーバーのアドレス
....
}
location /admin { # naxsi is disabled ※/admin以下はnaxsiは無効
SecRulesDisabled; # オプション、デフォルトではnaxsiは無効
allow 1.2.3.4;
deny all;
proxy_pass http://127.0.0.1;
....
}
location /vuln_page.php { # naxsi is enabled, and is *not* in learning mode
# ※この/vuln_page.phpはnaxsi有効で、学習モードでない(それ以外のページは上で指定されている学習モードになる)
SecRulesEnabled;
proxy_pass http://127.0.0.1;
}
location /RequestDenied { # ※上で指定されたnaxsiがブロックした場合のlocation
internal;
return 403;
}
...
}
4.動作確認
4.1 HTTPポート公開
ファイアウォールの設定で、httpのポートを開放する。
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
4.2 Nginx起動
設定したnginx.confに間違いが無いかチェックする。
nginx -t
問題が無ければnginxを起動する。
systemctl start nginx
4.3 Naxsi動作確認
ブラウザからWAFを叩いてテストする。
不正なパラメータ(<scrript>)を付けてURLを叩くと、ブロックが動作しているか確認できる。LearningModeの場合は、エラーログにメッセージが残るだけである。LearningModeでない場合は、エラーページが表示される。
通常ページがブロックされないか念入りに確認する。ブロックされた場合は、ホワイトリストを設定するか、そのページをNaxsiから除外するか、ルールを見直す等の対応をする。
5.公開
問題がなくなれば、正式にhttps化して公開する。
httpsポートの開放は以下。
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
Nginxを有効に。
systemctl enable nginx