先だっての記事で、「IPアドレス直打ちやヘッダーがないアクセスはたたき落とす」という設定を紹介しました。では、そういう直打ち以外の「きちんとこちらのホスト名、ドメイン名を調べ、そしてリクエストヘッダーも指定した攻撃はどういうものになるのか?」の実例を、筆者が実際に受けたログから紹介します。

1. 検出されたログの抜粋

以下は、検知されたエラーログの要約です(連続して複数のルールに抵触したため、重要なものを抜粋・統合しています)。

今回も攻撃者のIPアドレスは残しません。「テロリストに名前を与えてはいけない」からです。

# 1. Unicode難読化とプロトタイプ汚染の検知
[Date/Time] [security2:error] [client 192.0.2.1] ModSecurity: Warning. Pattern match "(?i)\\\\x5cu[0-9a-f]{4}" at ARGS:0. [file "REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [id "920540"] [msg "Possible Unicode character bypass detected"] [data "ARGS:0={\x22value\x22:\x22{\x5c\x22then\x5c\x22: \x5c\x22$B0\x5c\x22}\x22,\x22then\x22:\x22$1:__proto__:then\x22, ..."] [hostname "example.com"]

# 2. リモートコード実行(RCE)の検知
[Date/Time] [security2:error] [client 192.0.2.1] ModSecurity: Warning. Pattern match ... at ARGS:0. [file "REQUEST-932-APPLICATION-ATTACK-RCE.conf"] [id "932235"] [msg "Remote Command Execution: Unix Command Injection"] [data "Matched Data: eval)(global[\x5c\x22\x5c\x5cu0042... .from('KGFzeW5jIGZ1bmN0aW9uKCl7..."] [hostname "example.com"]

# 3. Node.js インジェクションおよびプロトタイプ汚染ルールの発火
[Date/Time] [security2:error] [client 192.0.2.1] ModSecurity: Warning. Pattern match ... [file "REQUEST-934-APPLICATION-ATTACK-GENERIC.conf"] [id "934100"] [msg "Node.js Injection Attack 1/2"]
[Date/Time] [security2:error] [client 192.0.2.1] ModSecurity: Warning. Pattern match "__proto__" at ARGS:0. [file "REQUEST-934-APPLICATION-ATTACK-GENERIC.conf"] [id "934130"] [msg "JavaScript Prototype Pollution"] [hostname "example.com"]

# 4. 異常スコア超過によるアクセス拒否(403)の実行
[Date/Time] [security2:error] [client 192.0.2.1] ModSecurity: Access denied with code 403 (phase 2). Operator GE matched 5 at TX:blocking_inbound_anomaly_score. [file "REQUEST-949-BLOCKING-EVALUATION.conf"] [id "949110"] [msg "Inbound Anomaly Score Exceeded (Total Score: 65)"] [hostname "example.com"]

2. 攻撃の意図

この攻撃の主な意図は、

  • サーバーの制御権の奪取(バックドアの設置)
  • クラウド認証情報の窃取」 です。

ログに記録されたペイロード(ARGS:0)を解析すると、以下の3つのステップを実行しようとしていたことが分かります。

  • プロトタイプ汚染 (Prototype Pollution):
    • JavaScript特有のオブジェクト仕様である __proto__then を悪用し、アプリケーション全体の挙動を書き換えようとしています。
  • 難読化によるWAFの回避:
    • Buffer という文字列を \u0042\u0075\u0066... のようにUnicodeエスケープし、WAFの単純な文字列チェックをすり抜けようとしています。
  • ペイロードの実行(RCE)
    • 送信データ内には Base64 でエンコードされたスクリプト(KGFzeW5j...)が含まれていました。これをデコードすると、// fast_recon_v6 — signature-rotated recon payload(自動偵察用スクリプト)というコメントが出現します。
    • 攻撃が成功すると、サーバー内部で eval() が実行され、AWSやGCPといったクラウド環境のメタデータ(IMDS)から認証情報を盗み出す、あるいは外部からコマンドを自由に入力できる状態(リモートコード実行)に陥る危険がありました。

3. 攻撃者の「技術スタック」

ログから推測される、この攻撃を仕掛けてきたボット(または攻撃者)の技術的な背景やツール群は以下の通りです。

  • 言語・ターゲット環境:
    • JavaScript / Node.js
    • ターゲットを完全に Node.js(Express や Next.js などのWebフレームワーク)に絞り込んでいます。
  • 使用ツール:
    • 既知の脆弱性スキャンツール(自動化ボット)
    • * ペイロード内のコメント(fast_recon_v6)から、アンダーグラウンドやオープンソースで流通している、あるいは独自に開発された高度な自動脆弱性スキャン・バックドア設置ツールキットである可能性が高いです。
  • インフラ(踏み台): クラウドサービス(Google Cloud など)
    • * 接続元IPを調査すると大手のパブリッククラウドに割り当てられたIPであり、攻撃者は自身のアドレスを隠すため、クラウド上のVPSや乗っ取ったサーバーを踏み台にしてスキャンを実行しています。

4. 攻撃が成功してしまった場合のシーケンス(最悪のシナリオ)

もしWebアプリケーション側に脆弱性があり、WAFを導入していなかった場合、攻撃は以下のように進行します。

sequenceDiagram participant Attacker as 攻撃者 participant Server as Webサーバー (Node.js) participant IMDS as クラウドメタデータ (IMDS) Attacker->>Server: 不正なJSONデータ (Prototype Pollution + Base64ペイロード) を送信 Note over Server: 脆弱性によりオブジェクトが汚染され、<br/>内部で eval() が実行される Server->>Server: 悪意あるスクリプト (fast_recon) が作動 Server->>IMDS: クラウドの認証情報 (IAMトークン等) をリクエスト IMDS-->>Server: 認証情報を返却 Server-->>Attacker: 盗み出した認証情報・サーバー情報を送信 Note over Attacker: サーバーの完全な制御権、<br/>およびクラウド全体の権限を掌握

5. 今回の ModSecurity が阻止した実際の動き

実際には、ModSecurity(OWASP CRS)がリクエストの段階で脅威を検知し、アプリケーションにデータが届く前に処理を遮断しました。

sequenceDiagram participant Attacker as 攻撃者 participant WAF as WAF (ModSecurity) participant Server as Webサーバー Attacker->>WAF: 不正なJSONデータを送信 (ホスト: example.com) Note over WAF: ルール 920540: Unicode難読化を検知<br/>ルール 934130: __proto__ (プロトタイプ汚染) を検知<br/>ルール 934100: Node.jsコード注入を検知 Note over WAF: 異常スコアを計算 (合計 65点 / 閾値 5点)<br/>スコア大幅超過のため、アクセスを拒否 WAF-->>Attacker: HTTP 403 Forbidden (アクセス拒否) Note over Server: 攻撃リクエストはサーバー(アプリ層)<br/>に到達せず、無傷で終了

6. そもそもの問題として

筆者のサイトにNode.jsは含まれていないというのがポイントです。筆者の技術スタックが

  • LAMP
  • もしくはRails

という枯れた技術だったのが幸いしていました。攻撃者は「Node.jsだと決めつけていた」のです。

自動スキャンは効率を重視します。相手が誰かではなく、「大量に存在する技術スタック」に対して決め打ちでペイロードを送りつけます。つまり、この攻撃は筆者個人を狙ったものではなく、「Node.jsで動いているなら当たれ」という散弾銃です。そして今回は、その散弾がたまたまLAMP環境に飛んできただけでした。

WAFはその誤射を淡々と403へ変え、ログだけを残しました。ログを読むということは、「何を防いだか」を知るだけではありません。攻撃者が世界をどう見ているかを知ることでもあるのです。

とはいえ、筆者がModSecurityで設定している

# 1-3. IPアドレス直打ちアクセス対策
SecRule REQUEST_HEADERS:Host "@rx ^[\d.]+(:\d+)?$" \
    "id:10004,\
    phase:1,\
    deny,\
    status:404,\
    log,\
    msg:'[CUSTOM RULE] Host header is a numeric IP address (incl port). Blocked immediately.',\
    tag:'application-attack',\
    tag:'PROTOCOL_VIOLATION/INVALID_HREQ'"

# Hostヘッダーが存在しない場合は即ブロック
SecRule &REQUEST_HEADERS:Host "@eq 0" \
    "id:10005,\
    phase:1,\
    deny,\
    status:404,\
    log,\
    msg:'[CUSTOM RULE] Missing Host Header. Blocked immediately.'"

を見事すり抜けました。つまり、きちんと筆者VPSのドメインを調べ、正しいHostヘッダーを付与してきたということです。この点については、攻撃者に敬意を表します。少なくとも、IPアドレス直打ちしかできないボットよりは、こちらを相手として認識していたのですから。そのおかげでWAF(ModSecurity)は仕事をし、評価を行い、その上でブロックしました。

この状況をたとえて言うならば『ジョジョの奇妙な冒険 戦闘潮流』の

まず、このワムウに殺される資格はあるッ!

といったところでしょうか。