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

こんにちは!インフラやセキュリティの世界へようこそ。
初めてサーバーOSの要塞化(ハーデニング)やコンテナセキュリティに向き合うとき、「なんだか難しそうな用語がいっぱい出てきて、どこから手をつけていいかわからない…」と不安になりますよね。

でも、大丈夫です!一歩ずつ、身近な例えから紐解いていけば、セキュリティは決して怖いものではありません。今回は、コンテナ技術を安全に使うための強力な盾である「Seccomp(セッコンプ)プロファイル」について、一緒に優しく学んでいきましょう!

—

1. 家の鍵で例える「システムコール」とセキュリティ

まずは、私たちが普段暮らしている「家」をイメージしてみてください。

あなたの家には玄関のドアがあり、外の世界とつながっていますよね。宅配便を受け取ったり、お出かけしたりするためにドアは必要不可欠です。
しかし、見知らぬ泥棒が勝手に勝手口や窓から侵入してこないように、普段は鍵をかけたり、不要な窓には格子をつけたりして対策をしますよね。

Linuxサーバーやコンテナの世界でも、これと全く同じことが起きているんです。

  • コンテナ(お部屋): アプリケーションが動いている安全な箱庭。
  • ホストOSのカーネル(家の外の世界・管理機能): メモリ管理やハードウェア制御など、何でもできる強力な中枢機能。
  • システムコール(玄関のドア): コンテナの中のアプリが、「ファイルを開きたい!」「ネットワーク通信をしたい!」とホストOSにお願いをするための連絡窓口(API)。

ここで問題になるのが、「アプリにとって本当にそんなにたくさんの玄関(システムコール)が必要ですか?」ということです。
Linuxカーネルには、なんと300種類以上ものシステムコール(ドア)が用意されています。しかし、Webアプリやデータベースが使うのは、そのうちのせいぜい数十個程度。

もし、泥棒(攻撃者)がアプリの脆弱性を突いてコンテナの中に侵入してきたとき、もし300個すべてのドアが開きっぱなしだったらどうなるでしょうか?
泥棒は使われていないマイナーなドアを探し出し、そこからホストOSの根幹を乗っ取ろうと暴れ回るでしょう。これが、カーネル脆弱性を突いたコンテナ破りの手口です。

—

2. Seccompってなに?不要なドアをピッチリ閉める仕組み

そこで登場するのが、今回の主役である Seccomp(Secure Computing Mode) です。

Seccompとは、一言で言うと「コンテナが勝手に使えるシステムコール(ドア)の数を制限し、いらないドアをあらかじめ塞いでおく番人」のようなものです。

Dockerなどのコンテナランタイムには、最初から「これくらいのシステムコールがあれば十分でしょう」というデフォルトのSeccompプロファイルが用意されています。これは非常に優秀で、約300個あるシステムコールのうち、危険なものや不要な約40個をあらかじめバツ印をつけて使えなくしてくれています。

しかし、開発するアプリケーションの性格によっては、「デフォルトのままだと少し緩すぎる」「うちのアプリはもっと特定のシステムコール以外使わないから、もっと厳しく制限したい!」というケースが出てきます。
そんなときに役立つのが、「Seccompプロファイルのカスタマイズ」です。

—

3. 実践!カスタムSeccompプロファイルの書き方

それでは、実際にカスタマイズされたSeccompプロファイル(JSON形式)の書き方を見てみましょう。
今回は、「基本的な操作は許可しつつ、危険なシステムコールである reboot(サーバーを再起動する命令)や swapon(スワップ領域を操作する命令)を完全に禁止する」というルールを作ってみます。

以下のコードを、実務では custom-seccomp.json という名前のファイルとして保存して使います。

{
  "defaultAction": "SCMP_ACT_ALLOW",
  "architectures": [
    "SCMP_ARCH_X86_64",
    "SCMP_ARCH_ARM64"
  ],
  "syscalls": [
    {
      "names": [
        "reboot",
        "swapon",
        "swapoff"
      ],
      "action": "SCMP_ACT_ERRNO",
      "args": []
    }
  ]
}

コードの解説(ここがポイント!)

1. "defaultAction": "SCMP_ACT_ALLOW"

  • 基本方針として、「ここに書いていない普通のシステムコールは、基本的には許可(ALLOW)するよ」という設定です。いきなり全部禁止にするとアプリが動かなくなってしまうため、まずは安全なデフォルトから始めます。

2. "architectures"

  • 実行するサーバーのCPUアーキテクチャ(x86_64やARM64など)を指定しています。

3. "syscalls" のブロック

  • ここで「例外的に禁止したいもの」を指定しています。
  • "names" に、reboot や swapon といった危険なシステムコールを並べています。
  • "action": "SCMP_ACT_ERRNO" は、「もしこの禁止されたドアをノックしようとしたら、エラー(許可されていないという返事)を返して追い返す」という意味になります。

—

4. Dockerコンテナにプロファイルを適用してみよう

作成したカスタムプロファイルは、Dockerを実行するときにオプションで簡単に適用できます。

実務の現場や検証環境では、以下のようにコマンドを実行します。

# --security-opt オプションを使って、作成したJSONファイルをDockerに読み込ませます
docker run --rm \
  --security-opt seccomp=./custom-seccomp.json \
  nginx:latest

たったこれだけで、このNginxコンテナの中からは、万が一ハッキングされても reboot などの危険なシステムコールが一切使えなくなります。ホストOSを守るための、非常に強力かつスマートな防壁の完成です!

—

まとめ:一歩ずつ、堅牢なシステムへ

今回は、Seccompプロファイルを使ったシステムコールの制限について、お家の鍵や泥棒の例えを交えながら解説しました。

  • コンテナからホストOSへの「窓口(システムコール)」は、実はそんなにたくさんは要らない。
  • デフォルトのままでも安全性が高まるが、アプリの特性に合わせてSeccompで不要なシステムコールを遮断(カスタム)するとさらに鉄壁になる。
  • 設定ファイル(JSON)は難しく見えても、禁止したい命令を並べるだけ。

「セキュリティ対策って、なんだか面倒くさそう…」と思っていた方も、こうして一つひとつの意味を紐解いていくと、自分の手でシステムを守る面白さが伝わったのではないでしょうか?

ぜひ、ご自身の検証環境や開発プロジェクトでも、このSeccompの設定にチャレンジしてみてくださいね。一歩ずつ、安全で強いインフラを作っていきましょう!

コメント

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