PR

WordPress を運用している Apache に ModSecurity を導入

セキュリティ
この記事は約14分で読めます。

※ この記事は 2024/04/05 に投稿され、 2024/04/05 に内容が更新されています

Web サイトのセキュリティは非常に重要です。
特に WordPress のような人気のある CMS を使用している場合、攻撃者のターゲットになる可能性が高くなります。
そのため、セキュリティ対策は必須です。

ModSecurity は、WordPress を運用している Apache など Web サーバにおけるセキュリティ強化のための優れたソフトウェアです。

本記事では、 ModSecurity を使って Apache で運用している WordPress のセキュリティを強化する方法と、その効果について詳しく説明します。
利用環境は Ubuntu Server 22.04 / Apache 環境となります。

ModSecurity を使って Web サーバのセキュリティ強化を

ModSecurity は WAFWeb Application Firewall として知られるツールで、 Apache をはじめとした Web サーバ上で動作します。

このソフトウェアは、攻撃を検知してブロックすることができるため、 WordPress のセキュリティを強化するのに非常に役立ちます。
ModSecurity は、 SQL インジェクション、クロスサイトスクリプティング (XSS)、リモートコード実行などのよく知られた攻撃パターンを検出し、ブロックすることができます。

WAF には「ソフトウェア型」「アプライアンス型」「クラウド型」と種類がありますが、 ModSecurity は「ソフトウェア型」であり、なおかつ OSS OpenSource Softwareのため無料で利用することができます。

当サイトは Cloudflare の無料版 WAF を利用しているのですが、残念ながらそれをもってしても、攻撃的なアクセスがあるという状況です。
そのため ModSecurity を導入することにしました。

※ 「IP アドレスは隠すべし」という批判はありましょうが、明らかに攻撃的意図があるアクセス元なので、そのまま晒しています

Apache 上の WordPress に ModSecurity を導入する手順

ModSecurity を Apache に導入するためには、まずはじめに ModSecurity をインストールする必要があります。
次に Apache の設定ファイルで ModSecurity を有効化し、ルールを追加します。

これにより、ModSecurity が WordPress のリクエストを監視し、検出した攻撃をブロックすることができます。
また、ModSecurity のログ機能を有効にして、攻撃の詳細情報を確認することも重要です。

導入 (apt)

Apache を apt でインストールされている場合は、簡単に導入することができます
modsecurity-crsCRSCore Rule Set で、つまり既知の攻撃などに対するルールセット (シグネイチャ) となります

パッケージインストール
apt update
apt install libapache2-mod-security2 modsecurity-crs
反映
# ModSecurity モジュールを有効化
sudo a2enmod security2

# 推奨設定を有効化
sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf

# Apache 再起動
sudo systemctl restart apache2.service

ただ、私はインフラエンジニアということもあり、脆弱性が発見されたら即パッチをあてるやバージョンアップ対応したいので、 Apache をソースからインストールしています。
なので、 ModSecurity もソースからインストールすることになります。

導入 (ソースからインストール)
前提パッケージインストール
apt update
apt install libpcre-dev yajl-tools yajl2 ssdeep libyajl-dev lib-lua5.3-dev
ビルド
# ディレクトリ移動
cd /usr/local/src

# ソースコードダウンロード
wget https://github.com/owasp-modsecurity/ModSecurity/releases/download/v2.9.7/modsecurity-2.9.7.tar.gz

# ソースコード解凍
# 知らない人もいたのが以外だけど、 a オプションは z とか j とか拡張子でよきにはからってくれるよ
tar xavf modsecurity-2.9.7.tar.gz

# ソースコードディレクトリに移動
cd modsecurity-2.9.7

# configure
./configure --with-apxs=[PATH_TO_APXS] --with-apr=[PATH_TO_APX_UTILS] --with-yajl --with-ssdeep --with-lua --with-libxml

# 4 は CPU コア数に合わせて修正
make -j4

# モジュールインストール
sudo make install

# CRS ダウンロード
mkdir /usr/share/modsecurity
cd /usr/share/modsecurity
git clone https://github.com/SpiderLabs/owasp-modsecurity-crs.git
apache でモジュール読込み
sudo vim [PATH_TO_httpd.conf]
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule security2_module modules/mod_security2.so
ModSecurity conf 読込み
cd [PATH_TO_HTTPD-CONF-DIR]/conf/extra/
cat << EOF > modsecurity.conf
<IfModule security2_module>
        SecDataDir /var/cache/modsecurity
        IncludeOptional /etc/modsecurity/*.conf
        IncludeOptional /usr/share/modsecurity-crs/*.load
</IfModule>
EOF
conf ファイル追加
sudo mkdir -p /etc/modsecurity/crs
sudo cd /etc/modsecurity
sudo cat << EOF > mod_security.conf
# ブロック有効化
SecRuleEngine On
# 検出のみ
#SecRuleEngine DetectionOnly
SecRequestBodyAccess On
SecRule REQUEST_HEADERS:Content-Type "(?:application(?:/soap\+|/)|text/)xml" \
    "id:'200000',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=XML"
SecRule REQUEST_HEADERS:Content-Type "application/json" \
    "id:'200001',phase:1,t:none,t:lowercase,pass,nolog,ctl:requestBodyProcessor=JSON"
SecRequestBodyLimit 2147483648
SecRequestBodyNoFilesLimit 2147483648
SecRequestBodyInMemoryLimit 1310720
SecRequestBodyLimitAction Reject
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"
SecRule MULTIPART_STRICT_ERROR "!@eq 0" \
    "id:'200003',phase:2,t:none,log,deny,status:400, \
    msg:'Multipart request body failed strict validation: \
    PE %{REQBODY_PROCESSOR_ERROR}, \
    BQ %{MULTIPART_BOUNDARY_QUOTED}, \
    BW %{MULTIPART_BOUNDARY_WHITESPACE}, \
    DB %{MULTIPART_DATA_BEFORE}, \
    DA %{MULTIPART_DATA_AFTER}, \
    HF %{MULTIPART_HEADER_FOLDING}, \
    LF %{MULTIPART_LF_LINE}, \
    SM %{MULTIPART_MISSING_SEMICOLON}, \
    IQ %{MULTIPART_INVALID_QUOTING}, \
    IP %{MULTIPART_INVALID_PART}, \
    IH %{MULTIPART_INVALID_HEADER_FOLDING}, \
    FL %{MULTIPART_FILE_LIMIT_EXCEEDED}'"
SecRule MULTIPART_UNMATCHED_BOUNDARY "!@eq 0" \
    "id:'200004',phase:2,t:none,log,deny,msg:'Multipart parser detected a possible unmatched boundary.'"
SecPcreMatchLimit 100000
SecPcreMatchLimitRecursion 100000
SecRule TX:/^MSC_/ "!@streq 0" \
    "id:'200005',phase:2,t:none,deny,msg:'ModSecurity internal error flagged: %{MATCHED_VAR_NAME}'"
SecResponseBodyAccess Off
SecResponseBodyMimeType text/plain text/html text/xml
SecResponseBodyLimit 524288
SecResponseBodyLimitAction ProcessPartial
SecTmpDir /usr/local/apache2/logs/mod_security/tmp
SecDataDir /usr/local/apache2/logs/mod_security/data
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABDEFHIJZ
SecAuditLogType Serial
SecAuditLog /usr/local/apache2/logs/mod_security/modsec_audit.log
SecArgumentSeparator &
SecCookieFormat 0
SecUnicodeMapFile unicode.mapping 20127
SecStatusEngine On
EOF
反映

sudo systemctl restart [apache サービス名]

ModSecurity の導入による WordPress セキュリティ向上の効果

ModSecurity を導入することで、WordPress のセキュリティと防御力を大幅に向上させることができます。
ModSecurity は攻撃の検出とブロックを自動的に行うため、攻撃者の害悪なリクエストを阻止することができます。

これにより、WordPress の脆弱性を悪用した攻撃やデータ漏洩を防ぐことができます。ModSecurity のルールセットを適切に設定することで、独自のセキュリティポリシーを実装し、WordPress のセキュリティを最適化することも可能です。

ですが、誤検出も多いです、、というのが実情です。

ModSecurity の恩恵を受けるための WordPress の最適な設定

/etc/modsecurity/mod_security.conf について、個人環境なのでいきなりブロック有効化にしています。
本来は DetectionOnly にしてログを見つつルールを調整していくべきものですね。

# ブロック有効化
SecRuleEngine On
# 検出のみ
#SecRuleEngine DetectionOnly

誤検知が多いと述べましたが、そのまま CRS を WorsPress に適用するとどうなるか見てみましょう。
記事を投稿あるいは編集してみます。

記事を更新すると不正アクセスと見做される

はい、 403 エラーになってますね。

HTTP/1.1 403 Forbidden
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Length: 199
Connection: close
Content-Type: text/html; charset=iso-8859-1
Date: Thu, 04 Apr 2024 17:33:10 GMT
Server: Apache

攻撃と思われるアクセスを検出すると、ログに以下のようなルールセットの名前と ID が刻まれます。
この場合のルールセットは RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf で ID が 949110 になります。

modsec_audit.log
This 'deny' is by default paired with a 'status:403' action.\n#\n# In order to change the disruptive action from 'deny' to something else,\n# you must use SecRuleUpdateActionByID directives AFTER the CRS rules\n# are configured, for instance in the RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf file.\n#\n# These actions only apply when using Anomaly Mode.\n#\n# Default action: block with error 403\n# (No configuration needed in this file if you want the default behavior.)\n#\n\n# Example: redirect back to the homepage on blocking\n#\n# SecRuleUpdateActionById 949110

ルールセット自体の読込みをやめる or ルールを除外するユーザ設定を追加しましょう。
ルールセットを読み込まない方法が確実ですが、その分セキュリティも下がるため、可能であれば ID を特定してルールだけを除外する方が良いです。

ルール追加

ルールをユーザ設定で除外するオーバーライド

書式は面倒ですが、やってることはシンプルです

  • HTTP メソッドが POST
  • リファラに therewill.be (利用ドメイン) を含む
    • ログインユーザ以外が投稿することはない = リファラが利用ドメイン以外になることはない
  • Cookie に wordpress_logged_in_ がある
    • ログイン済みユーザでないと空
  • 引っかかっていたルールは以下 ID なので、これだけ除外
    • 949110 / 941100 / 941160 / 941180 / 941310
cd /etc/modsecurity/
cat << EOF > user.conf
<If "%{REQUEST_METHOD} == 'POST' && (%{HTTP_REFERER} =~ /therewill\.be/ || %{HTTP_COOKIE} !~ /wordpress_logged_in_/)">
    SecRuleRemoveById 949110 941100 941160 941180 941310
</If>
EOF

まとめ

ModSecurity を活用するためには、 WordPress の設定も最適化する必要があります。
まず、常に最新のWordPress バージョンを使用し、セキュリティパッチを定期的に適用することが重要です。
また、不要なプラグインやテーマを削除し、セキュリティの脆弱性を減らすことも必要です。さらに、強力なパスワードポリシーを設定し、二要素認証を有効化することも推奨されます。

これらの設定は、ModSecurity との相乗効果を生み出し、WordPress のセキュリティをより強固にします。
ModSecurity を使って Apache 上の WordPress のセキュリティを強化することは、ウェブサイトの安全性を向上させるために重要です。

本記事では、ModSecurity の導入手順やその効果、WordPress の適切な設定について説明しました。

Apache 上で WordPress を運営している場合は、是非 ModSecurity を導入してセキュリティを強化してください。

ユーザ設定が面倒なところもありますが、ウェブサイトへの攻撃から保護するために、 ModSecurity は重要なソフトウェアとなるでしょう。

コメント