【実務・中級編】 Seccompプロファイルによるシステムコール制限の実装 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

コンテナの「最後の砦」:Seccompによるシステムコール制限の実践

エンジニア諸君、日々お疲れ様。本日は、コンテナセキュリティにおける「最後の砦」、Seccomp(Secure Computing mode)について話をしよう。

多くの開発者は、DockerやKubernetesにおいて「イメージの脆弱性スキャン」や「IAMの最小権限」には気を配る。だが、「コンテナがホストのカーネルをどれだけ自由に叩けるか」という視点が抜け落ちているケースが非常に多い。これが、攻撃者にカーネルの脆弱性を突かれ、コンテナ脱出(Container Escape)を許す最大の盲点だ。

なぜ、Seccompをカスタマイズする必要があるのか

デフォルトのDocker Seccompプロファイルは、約300個あるシステムコールのうち、40個以上をブラックリスト形式で遮断している。一見安全そうに見えるが、これらは「汎用的な安全性」を担保しているに過ぎない。

例えば、君たちが動かしているそのWebアプリ、本当に mount や ptrace、あるいは reboot が必要か? 答えはNOだろう。攻撃者は、アプリケーションの脆弱性(RCE等)を突いてシェルを奪取した後、これらの不要なシステムコールを駆使して、カーネルの未知の脆弱性(0-day)を叩く。

もし君が ptrace を禁止していれば、攻撃者がそのコンテナ内でデバッガを動かしてメモリを解析したり、プロセスを乗っ取ることは不可能になる。これが「防御的アプローチ」の神髄だ。

—

実践:最小権限のSeccompプロファイルを作成する

まずは、不要なコールを全遮断し、必要なものだけを許可する「ホワイトリスト方式」のJSONプロファイルを作成しよう。

以下の設定ファイル custom-profile.json を見てほしい。

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32"],
  "syscalls": [
    {
      "names": [
        "read", "write", "exit", "exit_group", 
        "epoll_wait", "epoll_ctl", "epoll_create1",
        "futex", "nanosleep", "getrandom"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}
  • defaultAction: SCMP_ACT_ERRNO を指定することで、リストにないシステムコールはすべてエラー(EPERM)を返して拒否する。これが重要だ。
  • names: アプリケーションが最低限必要なコールのみを記述する。Node.jsやPythonのランタイムによって必要なコールは異なるため、strace を使って事前にプロファイリングしておく必要がある。

—

コンテナへの適用と検証

作成したプロファイルは、Docker実行時にフラグとして渡す。

# プロファイルを指定してコンテナを起動
docker run --rm -it \
  --security-opt seccomp=custom-profile.json \
  alpine:latest /bin/sh

ここで、許可していない mount を試してみると、即座に Operation not permitted が返ってくるはずだ。これが、脆弱性を突こうとする攻撃者の行く手を阻む「壁」となる。

—

開発現場での泥臭い運用Tips

「どのシステムコールを許可すればいいかわからない」という声が聞こえてきそうだ。そんな時は、開発環境で strace を使ってアプリを動かし、必要なコールを抽出するのが定石だ。

# コンテナ内でアプリケーションをstraceし、コールをログに吐き出す
strace -c -f -o syscall_log.txt python3 app.py

この syscall_log.txt を解析し、実際に呼ばれているコールだけをプロファイルに転記する。「面倒くさい」と感じるかもしれないが、この「面倒くささ」の差が、インシデント発生時に「被害をコンテナ内で止めた」という結果を生む。

セキュリティチーフからの助言

最後に一つ。Seccompの設定は、あくまで多層防御の一つだ。

1. Read-only Root Filesystem: コンテナ実行時に --read-only フラグを併用せよ。攻撃者が悪意のあるスクリプトを配置する場所を物理的に消す。
2. Capabilitiesの削除: cap_drop_all を行い、必要な権限(CAP_NET_BIND_SERVICEなど)だけを付与する。

セキュリティは、魔法のようなツールで解決するものではない。こうした地味で泥臭い設定の積み重ねが、堅牢なインフラを作る。君たちの書くコードと同様に、セキュリティ設計も「シンプルで、明確で、目的がはっきりしている」ことが最も美しい。

さあ、明日から君たちのコンテナ環境の seccomp を見直してみよう。健闘を祈る。

コメント

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