泥沼の戦場で見つけた「出口のない迷宮」:/tmp と /var/tmp の noexec マウントを再考する
セキュリティの現場で数々のインシデントを見てきたが、攻撃者が侵入した際、最初に彼らが手を出すのは決まって /tmp だ。これは何も新しいことではない。だが、なぜ我々が何十年も前から推奨している /tmp の noexec マウントが、いまだに多くの本番環境で「形骸化」しているのか。
今日は、教科書的な「設定しましょう」という話はしない。カーネルレベルでの実行制御、そして攻撃者がその「壁」をどう突き崩そうとするのか、その深層心理と技術的防衛論を語ろう。
なぜ noexec は「最後の砦」なのか
攻撃者がWebシェルをアップロードし、あるいは脆弱性を突いてバイナリを配置する際、彼らは書き込み権限と実行権限の両方を同時に満たす場所を渇望する。現代のWebアプリケーション環境において、その条件を満たす唯一の「公衆便所」が /tmp や /var/tmp だ。
ここで、/etc/fstab に noexec を付与することで、カーネルは execve() システムコールに対して該当マウントポイント内のファイル実行を拒否する。これは単なる権限設定ではなく、OSのカーネル境界における「実行のガードレイル」だ。
# /etc/fstab の設定例
# tmpfs を使用してメモリ上にマウントし、noexec, nosuid, nodev を付与する
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev,size=1G,mode=1777 0 0
tmpfs /var/tmp tmpfs defaults,noexec,nosuid,nodev,size=1G,mode=1777 0 0
攻撃者の「裏口」:noexec をバイパスする泥臭いテクニック
しかし、経験豊富な攻撃者は、この noexec を「無力」だと笑う。なぜか。彼らはファイルを実行するのではなく、「実行権限のあるバイナリに実行させる」という手法を採るからだ。
1. インタプリタの悪用:
/tmp/exploit.py が実行できなくても、/usr/bin/python3 /tmp/exploit.py は実行できる。python は /usr/bin にあるため、実行権限を持つからだ。
2. メモリ内実行(Fileless Malware):
そもそもディスクに書き込まない。メモリ上にペイロードを展開し、memfd_create システムコールを用いて実行する。これはディスク上の noexec マウントとは無縁の領域で完結する。
つまり、noexec だけでは不十分だ。我々アーキテクトが目指すべきは、「多層的な実行制御」である。
次世代の防衛:アーキテクチャの多層化
noexec は必須の衛生管理だが、それ単体で満足してはいけない。以下の防衛レイヤーを重ねることで、初めてインフラとしての強度が担保される。
1. Mount Namespace と chroot / container の分離
アプリケーションを実行するプロセスに対して、/tmp を専用の tmpfs として隔離し、ホストOSとの物理的なパスを分断する。DockerやKubernetes環境であれば、SecurityContext を用いて徹底すべきだ。
# Kubernetes における SecurityContext の例
spec:
containers:
- name: app
securityContext:
# コンテナ内の /tmp を制限し、書き込み可能領域を最小化する
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
2. EDR/Auditd によるシステムコール監視
noexec をすり抜ける手法(python /tmp/... など)を検知するには、auditd を用いて、特定ディレクトリ配下での実行プロセスを監視し、異常な親子関係を持つプロセスを即座に Kill する自動化が不可欠だ。
# auditd ルール例:/tmp 配下で実行されたプロセスのログを記録する
-a always,exit -F arch=b64 -S execve -F dir=/tmp -k tmp_execution
監査の視点:アーキテクトは何を見るべきか
私が監査に入る際、まず確認するのは noexec が付いているかどうかではない。「noexec を外さざるを得ない正当な理由は設計書にあるか?」という点だ。
多くの現場では、デプロイやログ出力の利便性のために、安易に noexec を解除する。これは「セキュリティの負債」を積み上げていることに他ならない。もし特定のアプリケーションがどうしても /tmp での実行を必要とするのであれば、それはアプリケーション設計の欠陥(アンチパターン)である可能性が高い。
結論:技術は「信頼」を補完するに過ぎない
noexec は強力だが、あくまでパッシブな防御だ。攻撃者は常に「OSの仕様の隙間」を縫って進んでくる。
我々が真に備えるべきは、/tmp をロックダウンすることに加え、「万が一、攻撃者がコードを実行できた際に、その先のネットワーク接続や権限昇格をどう制限するか」という、ゼロトラストの思想をシステムアーキテクチャ全体に組み込むことだ。
セキュリティとは、穴を塞ぐことではない。穴が空いていることを前提に、その先で敵をいかに無力化するかという「迷宮」を設計することである。あなたの構築したシステムは、攻撃者にとって「出口のない迷宮」になっているだろうか?
コメント