特権昇格の「一丁目一番地」を潰せ:Linuxファイルシステム権限のリアルな要塞化
インフラエンジニア諸君、お疲れ様。数々のインシデントを見てきたが、Webアプリの脆弱性で侵入に成功した攻撃者が、次に何をするか知っているか?
彼らは、OSの深部へ潜り込むための「足場」を探す。その際、最も手っ取り早いのがSUID/SGIDビットの悪用と、書き込み権限のあるディレクトリからの野良バイナリ実行だ。教科書には「不要なサービスを止めろ」としか書いていないかもしれないが、現場の泥臭い戦いでは、OSの権限設計そのものが防御の最後の砦になる。
今回は、Linuxを「物理的に壊す」レベルで堅牢にするための、実践的なファイルシステム・ハーデニングについて解説する。
—
1. SUID/SGIDという「時限爆弾」の解体
SUID(Set User ID)がセットされたファイルは、実行時に「そのファイルの所有者」の権限で動作する。もしそれが root 所有で、かつ脆弱性のあるバイナリだったら? 攻撃者は一瞬でシステムを乗っ取る。
まずは、システム内に潜む「危険なSUIDファイル」をあぶり出すことから始めよう。
探索コマンド
以下のコマンドを叩けば、システム内のSUID/SGIDが一覧できる。
# 権限のない不要なSUID/SGIDファイルをリストアップ
find / -perm /6000 -type f 2>/dev/null
ここで重要なのは、「本当にそのプログラムにSUIDが必要か?」を問うことだ。例えば、Webサーバーが動くコンテナ内で pkexec や古い mount コマンドにSUIDが付いていたら、即座に削除するか、実行権限を剥奪する。
対策:不要なビットの削除
# 特定のバイナリからSUIDビットを削除する例
sudo chmod u-s /usr/bin/some_risky_binary
—
2. /tmp と /var/tmp を「無害化」する
攻撃者は、Webアプリ経由でアップロードしたシェルスクリプトやバイナリを /tmp に置き、それを実行して権限昇格を狙う。これを防ぐための鉄則は、 /tmp 以下でのバイナリ実行を物理的に拒絶することだ。
マウントオプションの変更
/etc/fstab を編集し、以下のオプションを付与して再マウントする。これが最も確実な防御だ。
# /etc/fstab の設定例
# nosuid: SUIDビットを無視
# noexec: ファイルの実行を禁止
# nodev: デバイスファイルを無視
tmpfs /tmp tmpfs defaults,nosuid,noexec,nodev 0 0
tmpfs /var/tmp tmpfs defaults,nosuid,noexec,nodev 0 0
設定後、mount -o remount /tmp で即時反映させることを忘れるな。これにより、Webアプリから書き込まれたバックドアが、たとえ実行権限(chmod +x)を持っていたとしても、OSレベルで実行がブロックされる。
—
3. アプリケーション層からの防御:open_basedir との併用
インフラ側で対策しても、アプリ側に穴があっては意味がない。PHPを使用しているなら、php.ini でファイルシステムへのアクセスを物理的に制限しておくのが「多層防御」だ。
PHP設定例:php.ini
特定のディレクトリ以外へのアクセスを完全に遮断する。
; アプリケーションのルートディレクトリ以外へのファイル操作を禁止する
; これにより、/tmp や /etc 等への不正アクセスをアプリケーション層で防ぐ
open_basedir = /var/www/html:/var/lib/php/session
; 危険な関数の無効化(exec系は特権昇格の温床)
disable_functions = exec,passthru,shell_exec,system,proc_open,popen
—
4. 現場の教訓:なぜ「設定」が破られるのか
よくある失敗は、「自動更新やデプロイ時に、これらのセキュリティ設定が上書きされて消える」ことだ。
現場で私が徹底させているのは、AnsibleやTerraformのコードを「セキュリティの正解」にすること。手動で設定を変えるな。以下は、Ansibleでファイルをセキュアに管理するためのタスク例だ。
# Ansibleのタスク例:重要なディレクトリの権限を強制固定する
- name: Ensure /tmp is mounted with noexec
mount:
path: /tmp
src: tmpfs
fstype: tmpfs
opts: defaults,nosuid,noexec,nodev
state: mounted
—
最後に:完璧な防御など存在しない
今回の設定を行えば、攻撃者が特権昇格を狙う際の「定石」の多くは無効化できる。しかし、忘れないでほしい。セキュリティとは「終わりのないメンテナンス」だ。
- カーネルの脆弱性が出れば、いくらファイルシステムを固めても突破される可能性がある。
- だからこそ、「侵入されることを前提」に、
/tmpを塞ぎ、open_basedirで囲い込み、不要なSUIDを消す。
この積み重ねが、君のサービスを、そして君自身を、夜中に鳴り響くインシデントアラートから守る唯一の道だ。今日帰る前に、自分のサーバーの /etc/fstab を一度確認してみてくれ。それが、プロのエンジニアの流儀だ。
コメント