【実務・中級編】 不要なSUID/SGIDビットの探索と削除 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

権限昇格の「隠れた近道」を断つ:SUID/SGIDの徹底的な断捨離術

現場で数多のインシデントを見てきた経験から言わせてもらうと、サーバーが陥落する瞬間の多くは、派手なゼロデイ脆弱性ではなく、「足元に転がっていた小さな権限設定の不備」が原因だ。

特にLinuxにおける SUID (Set User ID) と SGID (Set Group ID) ビットは、攻撃者にとっては「宝の山」に見える。一般ユーザーで侵入した攻撃者が、root権限を奪取してサーバーを完全に掌握するための「踏み台」として、これほど都合の良い仕組みはないからだ。

今日は、教科書的な説明は抜きにして、実戦でどうやってこれらを洗い出し、無効化していくかという「泥臭い防衛術」を伝授する。

—

なぜSUID/SGIDが「悪魔の扉」になるのか

SUIDが設定されたファイルは、誰が実行しても「そのファイルの所有者(多くの場合root)」の権限で動作する。もし、そのプログラムに脆弱性があったり、環境変数を操作できたりすれば、攻撃者は一瞬でrootシェルを手に入れることができる。

攻撃者が狙う「お決まりのPoC」

例えば、古びた find コマンドや vim にSUIDが付与されていたとする。攻撃者は以下のようなコマンドで、あっけなくroot権限を奪う。

# SUIDが付与されたvimを悪用してrootシェルを起動する例
# 攻撃者はただvimを立ち上げ、その中でシェルを呼ぶだけだ
/usr/bin/vim.basic -c ':!/bin/sh'

これだけで、ゲームセットだ。だからこそ、サーバーの要塞化(ハーデニング)において、不要なSUID/SGIDの削除は「最初に行うべき儀式」なのだ。

—

実践:システム内のSUID/SGIDを洗い出す

まず、現状把握だ。以下のコマンドを叩いて、システム内に潜む「爆弾」をリストアップしてほしい。

# 権限昇格の可能性が高いSUID/SGIDファイルを抽出するコマンド
# 誤検知を防ぐため、システムディレクトリを中心にスキャンする
find / -perm /6000 -type f 2>/dev/null | xargs ls -la

ここで重要なのは、「なぜそのファイルにSUIDが必要なのか?」を自問自答することだ。passwd や sudo のように必要なもの以外は、すべて「不要」とみなすべきだ。

—

自動化して「セキュリティの穴」を塞ぎ続ける

手作業での確認は一度で終わりではない。パッチ適用やパッケージの追加で、いつの間にかSUIDビットが付与されることもある。以下のPythonスクリプトを定期実行(Cron)し、不審なSUIDファイルが増えていないか監視する仕組みを構築しておこう。

import os
import subprocess

def check_suid_files():
    """
    システム内のSUIDファイルをスキャンし、許可リスト外があれば警告を出す
    """
    # 許可するSUIDファイル(最小限に絞るべき)
    allowed_suid = {'/usr/bin/passwd', '/usr/bin/sudo', '/usr/bin/chsh'}
    
    # SUID/SGIDファイルを検索
    cmd = ["find", "/", "-perm", "/6000", "-type", "f"]
    result = subprocess.run(cmd, capture_output=True, text=True)
    
    found_files = result.stdout.splitlines()
    
    for file in found_files:
        if file not in allowed_suid:
            print(f"[ALERT] 未承認のSUID/SGIDファイルを発見: {file}")
            # ここでSlack通知やメールを送る処理を組み込むのがベター

if __name__ == "__main__":
    check_suid_files()

—

現場で守るべき「3つの鉄則」

最後に、インフラ設計者として君たちに守ってほしい鉄則を記す。

1. マウントオプションで防御する: データ領域(/home や /tmp)が別パーティションなら、/etc/fstab で nosuid オプションを付与する。これだけで、攻撃者がアップロードしたバイナリにSUIDビットを付けても無効化できる。

# /etc/fstab の例
    /dev/sdb1 /home ext4 defaults,nosuid,nodev 0 2

2. 不要なバイナリは削除する: コンパイル環境(gcc 等)や、実行にSUIDを必要とする古いツールをサーバーから取り除く。攻撃者は「現地調達」ができないだけで戦意を喪失する。
3. root権限の分離: コンテナ化を進め、アプリケーションプロセスには決してroot権限を与えない。Dockerfile で USER 指定を忘れずに行うこと。

# セキュアなDockerfileの例
FROM alpine:latest
# root以外のユーザーで実行する
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
CMD ["./my-web-app"]

結び

セキュリティとは、完璧を目指すことではない。「攻撃者がコストを払ってまで突破したくなくなる環境」を作ることだ。

SUID/SGIDの整理は地味だが、攻撃者にとっては非常に嫌なハードルになる。こういった「基礎体力の向上」こそが、大規模な被害を防ぐ唯一の近道だと心得ておいてほしい。明日からの運用で、ぜひこのスキャンを組み込んでみてくれ。健闘を祈る。

コメント

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