コンテナの「中」で何が起きているか、見えているか?―― Falcoで実現するランタイムセキュリティの急所
エンジニア諸君、日々お疲れ様。本番環境のコンテナを「ブラックボックス」のまま運用していないだろうか?
「Dockerイメージをスキャンしているから大丈夫」「クラウドのIAM設定は完璧だ」……そう豪語するエンジニアほど、インシデント発生時に「コンテナ内でいつの間にか sh が叩かれ、外部と通信されていた」という現実に直面して青ざめるものだ。
今日は、暗号技術で通信を固める以前の、「コンテナが乗っ取られた後の泥臭い防衛戦」、すなわちランタイムセキュリティについて話そう。
—
1. なぜ「静的解析」だけでは不十分なのか
Webアプリ開発者がよくやるミスは、コードの脆弱性修正(SQLiやXSS対策)に集中しすぎて、「実行環境そのものへの侵入」を考慮から外すことだ。
攻撃者は、アプリケーションの脆弱性を突いてシェルコードを実行させる。一度コンテナ内に侵入してしまえば、そこは彼らの「自由の国」だ。暗号理論でいかに強固な鍵(RSAやECC)を使っていても、OSプロセスとして実行される curl や ncat を使われれば、メモリ上の機密データは容易に外部へ持ち出される。
ここで登場するのが Falco だ。これは単なるログ監視ではない。カーネルレベル(eBPFやカーネルモジュール)でシステムコールをフックし、「コンテナ内での異常な挙動」をリアルタイムで検知する「最後の砦」だ。
—
2. 実践:Falcoによる「シェル起動」検知設定
コンテナ内で sh や bash が起動されることは、通常のWebアプリ運用ではまずあり得ない。これを見逃さないための設定ファイルを共有する。
custom_rules.yaml の実装例
この設定は、コンテナ内でのシェル起動を検知してログを吐き出すためのものだ。
- rule: Shell in Container
desc: コンテナ内でシェルが起動されたことを検知
condition: >
container.id != host and
proc.name in (sh, bash, zsh, dash) and
proc.pname != "python3" # 正規の管理用スクリプトを除外する場合
output: >
警告: コンテナ内でシェルが起動されました。
(user=%user.name container_id=%container.id container_name=%container.name
shell=%proc.name parent_process=%proc.pname cmdline=%proc.cmdline)
priority: WARNING
この設定をFalcoに読み込ませることで、攻撃者がリバースシェルを貼ろうとした瞬間にアラートが飛ぶ。運用担当者は、このアラートが鳴った時点で「コンテナを即時隔離(Kill)」する自動化パイプラインを組むべきだ。
—
3. なぜ「暗号」の話が必要なのか:証明書の悪用を防ぐ
コンテナ内への侵入者は、次に何を狙うか? そう、環境変数に含まれるAPIキーや、ローカルにマウントされた秘密鍵(id_rsa 等)だ。
たとえTLSで通信を暗号化していても、アプリケーションプロセスがメモリ上に展開した平文の秘密鍵を盗まれたら元も子もない。ここで重要になるのが、「証明書や鍵のライフサイクルをコンテナ内に持たせない」という思想だ。
Pythonでの機密情報ハンドリング(悪い例と良い例)
多くのエンジニアは、設定ファイルに鍵を直書きしてしまう。
# 悪い例: 環境変数やファイルから直接読み込む
# 攻撃者がコンテナに入れば、os.getenv('SECRET_KEY') で一撃
import os
SECRET_KEY = os.getenv('SECRET_KEY')
推奨される設計:
AWS Secrets ManagerやHashiCorp Vaultを使い、アプリケーション起動時に「メモリ内」のみで鍵を保持する設計にすること。以下のコードは、アプリケーションが侵害されても、物理ファイルから鍵が流出するリスクを最小化する例だ。
# 良い例: メモリ内のみで完結させる設計指針
import secrets
def get_session_key():
# 物理ファイルに書き出さない。
# 可能な限りランタイムで動的に生成するか、Vaultから直接取得する
return secrets.token_hex(32)
# コンテナ監視(Falco)と組み合わせることで、
# 万が一シェルが起動されても、重要な秘密鍵はメモリの断片としてしか存在せず、
# プロセスダンプの難易度を格段に引き上げることができる。
—
4. 現場の知見:セキュリティは「設定」で終わるな
最後に、後輩たちに伝えておきたいことがある。
セキュリティツールを入れただけで安心してはいけない。Falco も WAF も、結局は「攻撃者のパターン」に依存する。重要なのは、「異常な挙動を検知した後のハンドリング」だ。
- 自動隔離: アラート発報と同時に
kubectl delete podを走らせるのか? - フォレンジック: 隔離したコンテナのメモリダンプを即座に取得する仕組みがあるか?
- イミュータブル・インフラ: コンテナを「使い捨て」にする運用を徹底できているか?
「完璧な防御」などこの世には存在しない。あるのは「攻撃者のコストを跳ね上げ、侵入を諦めさせる多層的な設計」だけだ。
今日から、自身のコンテナで docker exec -it <container_id> sh と打って、自分の監視システムが即座に反応するか試してみるといい。それが、エンジニアとしての最初の防衛訓練になるはずだ。
—
執筆者:セキュリティチーフエンジニア
*CISSP、OSCP保持。防衛の要は、テクノロジーへの深い理解と、常に「最悪の事態」を想定する冷徹な想像力に宿る。*
コメント