【実務・中級編】 Linuxにおけるファイルシステム権限の厳格化 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

特権昇格の「一丁目一番地」を潰せ: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 を一度確認してみてくれ。それが、プロのエンジニアの流儀だ。

コメント

タイトルとURLをコピーしました