ログは「信頼できない第三者」と思え:ログインジェクションから身を守る実務的アプローチ
現場でインシデント対応をしていると、往々にして「ログは嘘をつかない」と信じ込んでいるエンジニアに出くわす。だが、断言しよう。攻撃者にとって、ログファイルは改竄可能な「偽造工作のキャンバス」だ。
ログインジェクション(Log Injection)は、派手なSQLインジェクションに比べれば地味に見えるかもしれない。しかし、この攻撃はセキュリティ担当者の目を欺き、隠蔽工作や調査の攪乱を引き起こす、非常に巧妙な罠だ。今日は、この泥臭いけれど致命的な脆弱性について、実戦的な防衛策を叩き込む。
—
1. なぜ「ログ」が狙われるのか?(攻撃メカニズム)
ログインジェクションの本質は、「アプリケーションが信用して出力するログ」に「攻撃者が制御文字(CR/LF等)を混ぜ込むこと」にある。
例えば、ログイン失敗時にユーザー名を表示する以下のようなログコードがあったとしよう。
// 脆弱な実装例
$username = $_POST[‘username’];
error_log(“Login failed for user: ” . $username);
もし攻撃者が、ユーザー名として admin\n[2023-10-27 10:00:00] INFO: Login success for user: admin という文字列を送り込んだらどうなるか? ログファイルは以下のように出力される。
[2023-10-27 09:59:59] ERROR: Login failed for user: admin
[2023-10-27 10:00:00] INFO: Login success for user: admin
管理者はログを見て「ああ、adminがログインに成功したのか」と誤認する。これが、ログの偽造による攻撃の基本だ。SIEM(セキュリティ情報イベント管理)で監視していても、ログ自体が書き換えられていれば、検知は不可能になる。
—
2. 完封するための「構造化ログ」という解
「入力値をサニタイズすればいい」という議論は、正直古い。正規表現で改行文字を削除しても、バイナリデータや未知の制御文字を突きつけられたら穴が開く。
現代の防衛の最適解は「構造化ログ(JSON形式)」の採用だ。
ログをプレーンテキストではなく、JSONで出力する。これだけで、ログ解析ツールはデータを「値」として正しく認識し、改行コードが含まれていても「ひとつのフィールド内の文字列」としてパースするため、ログの行構造が崩れることはない。
実装例:Pythonによる構造化ログ(loggingモジュール)
Pythonの json-logger を使えば、実装は一瞬だ。
import logging
from pythonjsonlogger import jsonlogger
ロガーの初期化
logger = logging.getLogger()
logHandler = logging.StreamHandler()
JSONフォーマッタの定義
formatter = jsonlogger.JsonFormatter(‘%(asctime)s %(levelname)s %(message)s’)
logHandler.setFormatter(formatter)
logger.addHandler(logHandler)
攻撃者が改行を含めた文字列を送ってきても、JSONなら安全
malicious_input = “attacker\n[INFO] User logged in as admin”
logger.warning(“Login failed”, extra={“username”: malicious_input})
出力結果:
{“asctime”: “2023-10-27…”, “levelname”: “WARNING”, “message”: “Login failed”, “username”: “attacker\n[INFO] User logged in as admin”}
このようにJSON化していれば、どんな悪意ある文字列を注入しようが、それはあくまで username フィールドの中身であり、システムログの行構造を破壊することはできない。
—
3. インフラ側での防御:WAFとパーミッション
開発側で構造化ログを導入するのが筋だが、レガシーなシステムを即座に修正できない場合は、防御層を重ねる必要がある。
WAFによるリクエスト遮断
CloudFrontやAWS WAF等の設定で、改行コード(%0A, %0D)を含むリクエストをフィルタリングする。
- WAFのカスタムルール設定例 (Regex Pattern Match):
- 対象:
URI/Query String/Body - パターン:
(%0A|%0D|\n|\r) - アクション:
BLOCK
ログファイルのパーミッション管理
インシデント発生時、攻撃者はログを消去したり、偽のログを追記しようとする。
- 原則: ログファイルへの書き込みは「アペンドのみ(Append-only)」の権限にする。
- Linux設定例:
# ログファイルに追記のみ許可し、削除や編集を不可にする
chattr +a /var/log/app/access.log
これをしておくだけで、万が一アプリケーションが突破されても、攻撃者が過去のログを改竄するハードルを劇的に引き上げることができる。
—
最後に:エンジニアとしての矜持
セキュリティ対策は「チェックボックスを埋める作業」ではない。攻撃者が何を考え、システムのどの隙間を突いて、どうやって証拠を隠滅しようとしているかを想像するゲームだ。
ログを単なる「記録」と捉えず、「攻撃者が書き換えを狙う攻撃対象(アタックサーフェス)」と見なすこと。それが、君が現場で真に信頼されるエンジニアになるための第一歩だ。
コードを書くときは、常に「もし、この文字列に悪意が詰まっていたら?」という問いを自分に投げかけてくれ。それが、我々セキュリティを生業とする者の、最低限にして最大の責任なんだから。
コメント