Skip to main content

PHPコンテナのセキュリティを強化する

著者
Headshot of Neema Muganga

Neema Muganga

feature safe containers

2022年8月4日

0 分で読めます

Wappalyzerによると、PHPは1,200万以上のウェブサイトで使われています。28年の歴史を持つ言語としては、なかなかのものです。長い歴史がありながら、PHPは現代の開発プラクティスに対応し続けています。型宣言に対応し、LaravelやSymfonyなど優れたフレームワークもあるPHPは、今でもウェブアプリ開発に適した選択肢です。

PHPはコンテナ化された環境での利用に適しています。Docker Hubでは公式イメージが提供されているため、開発者は十分にテストされたPHPコンテナイメージを利用して開発を始められます。

それでも、PHPアプリケーションのコンテナイメージをビルドする際には注意が必要です。PHPは広く普及し、多く使われているため、攻撃者にとって魅力的な標的となります。また、コンテナやマイクロサービスを利用する環境では、PHPコンテナをサードパーティ製アプリケーションと併用することも多く、脆弱性につながる経路がさらに増えます。

コンテナによる分離を理由に、コンテナは本質的に安全だと考えてしまう開発者は少なくありません。この誤った思い込みは、セキュリティへの油断につながります。セキュリティを常に意識することは欠かせませんが、少しの注意と慎重さがあれば、安全なPHPコンテナアプリの開発と実行は難しくありません。

それでは、PHPコンテナのセキュリティを強化するベストプラクティスを、実際に手を動かしながら見ていきましょう。

前提条件

これらのベストプラクティスを実践し、このデモに沿って進めるには、次のツールを用意してください。

  • お使いのマシンにDockerをインストールします。PHPコンテナの実行と、Dockerに組み込まれている機能を使ったセキュリティ強化に利用します。

  • Snykの無料アカウントを用意します。Snykのセキュリティスキャンツールを使って、コンテナの脆弱性を見つけ、修正します。

  • Snyk CLIのインストールと実行に使うNode.js。または、ほかの方法についてはSnyk CLIのインストールに関するドキュメントをご覧ください。

覚えておきたいコンテナのベストプラクティス

コンテナはPHPアプリを実行するうえで便利です。Dockerなどのコンテナランタイムは、コンテナ同士やホストOSからコンテナを分離しますが、その分離は完全ではなく、過去には回避された事例もあります。

PHPコンテナのセキュリティを強化するには、次のような対策があります。

リソース制限とクォータを設定する

コンテナごとにリソースクォータを設定すると、コンテナが使用できるシステムリソースの量を制限できます。対象となるリソースには、コンテナが使用するメモリやCPU、ディスクI/O帯域幅などがあります。PHP開発者は、いくつかのコンテナランタイムオプションを利用して、コンテナがアクセスできるリソースを制限できます。

CPU

–-cpus <value>フラグを使うと、コンテナが使用できるCPU数を指定できます。たとえば--cpus 3.5と設定すると、使用可能なCPUまたはCPUコアのうち、ちょうど3.5個分をコンテナが使用できます。

より細かく制御する必要がある場合は、cpu-quotaおよびcpu-periodフラグについてDockerのドキュメントをご覧ください。ただし、これらのフラグを効果的に使うには、Linuxのスケジューラ期間について理解しておく必要があります。

CPU使用量を制限してPHPコンテナを実行する例を紹介します。

$ docker run -it --cpus 3.5 php:7.4-cli /bin/bash

メモリ

-mまたは–memory=フラグを使うと、コンテナが使用できるメモリの上限を設定できます。正の整数の末尾にb、k、m、gを付けることで、それぞれバイト、キロバイト、メガバイト、ギガバイトを指定できます。

たとえば、次のコマンドを使うと、コンテナのメモリ予約を800MBに制限し、RAMの最大容量を1.5GBに設定できます。

$ docker run -it --memory 1.5g --memory-reservation 800m php:7.4-cli /bin/bash

コンテナが利用できるリソースを制限すると、攻撃による潜在的な影響を最小限に抑えられます。コンテナが大量のリソースを消費し、ホストOSやほかのコンテナの動作を妨げる可能性が低くなるためです。この対策は各コンテナのセキュリティを高めるだけでなく、ホスト環境全体のセキュリティ向上にもつながります。

クォータのないコンテナは、システムをサービス拒否(DoS)攻撃に対して脆弱な状態にします。DoS攻撃によってシステム上のサービスが停止し、利用者へのサービス品質が低下するおそれがあります。このように、クォータのないコンテナを適切に管理しなければ、ビジネス上のセキュリティリスクになり得ます。

DockerではなくKubernetesでPHPコンテナを実行する場合、コンテナのセキュリティを維持するうえでKubernetesのコンテキスト設定を理解することが重要です。

コンテナをrootで実行しない

コンテナをrootユーザーとして実行したり、必要以上の権限を持つユーザーアカウントで実行したりするのは避けましょう。コンテナ用のユーザーアカウントを作成するときは、常に最小権限の原則に従う必要があります。

ほとんどのコンテナランタイムでは、root以外のユーザーアカウントでコンテナを実行できます。Dockerには、通常のユーザーアカウントでコンテナランタイムとそのすべてのコンテナを実行するためのrootlessモードがあります。

Kubernetesにも、rootlessノードとコンテナを実行するためのオプションがいくつか用意されています。さらに、OCI準拠のコンテナランタイムであれば、ランタイム設定ファイルのUIDとGIDのプロパティを使って、ランタイムが使用するユーザーとグループを正確に指定できます。

Snykを使ってKubernetesの設定ファイルやTerraformのIaCファイルをスキャンしている場合、上記のような設定ミスも検出できます。たとえば、メモリ制限が未設定、コンテナがrootとして実行されているといった問題を視覚的に示し、セキュリティのベストプラクティスに従っていないYAMLファイル内の該当行も提示します。

セキュリティ分析でKubernetesコンテナの問題が検出され、DeploymentのYAMLではホストPIDの共有、メモリ制限の未設定、特権設定が示されています。

Dockerを例にすると、PHPコンテナをrootlessモードで実行する方法は、Dockerをrootで実行する場合と大きく変わりません。通常のDockerコマンドはほぼそのまま使えますが、コンテナに付与できる権限は、Dockerデーモンを実行しているユーザーアカウントの権限に制限される点に注意してください。ただし、注意点が1つあります。Dockerデーモンをデフォルト設定でインストール済みの場合は、アンインストールしてから、Dockerのドキュメントの手順に従ってrootlessモードで再インストールする必要があります。

コンテナ内でrootユーザーを使わない

コンテナをrootlessモードで実行するだけでなく、コンテナ内でもrootユーザーの使用を避けましょう。すでにrootlessモードで実行しているなら冗長に思えるかもしれませんが、悪意のあるユーザーに対する防御をさらに強化できます。

DockerfileでUSERディレクティブを使うと、必要最小限の権限を持つユーザーまたはグループのコンテキストでPHPコンテナを実行できます。

Dockerのベースイメージに権限の低いユーザーが含まれていない場合は、イメージのビルド時にroot以外のユーザーを追加できます。次のDockerfileの例のように、新しいコンテナイメージを作成するときにそのユーザーを利用できます。

FROM php:7.4-cli
# the command below adds a new user or a group with a userid 1002
RUN groupadd -g 1002 appuser && \
    useradd -r -u 1002 -g appuser appuser
# command below changes a default root user to one with non-root privileges
USER appuser
CMD ["touch", "/root/example.txt"]

PHPの公式コンテナイメージには、nobodyという名前の非特権ユーザーアカウントが含まれています。そのため、Dockerの公式ベースイメージを使ってコンテナイメージをビルドする場合は、自分でユーザーを作成せずに、このユーザーを利用できます(上記の例を参照)。

FROM php:7.4-cli
USER nobody
CMD ["touch", "/root/example.txt"]

Dockerイメージを対話モードで実行し、Dockerfileでrootユーザー用に作成したテキストファイルを確認しようとすると、アクセスできないことがわかります。

$ cat /root/example.txt
cat: /root/example.txt: Permission denied

重要なのは、実行時とコンテナ内の両方でrootの使用を避けることです。そうすれば、悪意のあるDockerアプリケーションイメージや侵害されたコンテナアプリケーションがホストOSに侵入し、そこからラテラルムーブメントを続けるには、権限昇格攻撃を2回成功させる必要があります。

ただし、常にrootlessコンテナを使えるとは限りません。コンテナ化されたアプリケーションがGPUなどのハードウェアにアクセスする必要がある場合もあります。そのようなときは、防御をさらに強化する方法があります。

自動化ツールでコンテナの脆弱性を修正する

コンテナには、数多くの脆弱性が潜んでいる可能性があります。ベースイメージに含まれるライブラリやアプリケーション、追加でインストールしたパッケージに、CVEなどの脆弱性が含まれているかもしれません。その場合、どうすれば気づけるでしょうか。多くの開発チームやDevOpsチームには、コンテナにインストールされたすべてのパッケージのセキュリティ履歴を手作業で追跡する時間はありません。

幸い、自動コンテナスキャンが役立ちます。Snyk Containerは無料で利用でき、イメージを自動でスキャンして、コンテナ内のパッケージやオープンソースライブラリにある脆弱性をすぐに通知します。脆弱性が見つかったら、攻撃者に悪用される前に修正を適用できます。また、更新済みのベースイメージと推奨イメージタグを使ったプルリクエストを作成し、修正を自動で提案します。

Snykを使えば、コンテナの脆弱性をすばやく簡単にスキャンできます。Node.jsとnpmがインストールされていれば、npm install snyk@latest -gを実行してSnyk CLIをインストールするだけです。

次に、以下を実行します。

snyk auth

このコマンドを実行すると、ブラウザーで認証ページが開きます。

Snyk CLIでマシンを認証するようユーザーに促すSnykのWebページ。「Authenticate」ボタンが表示されている

"blog-php-container-authenticateターミナルに認証成功のメッセージが表示されます。Authenticateボタンをクリックしてください。

これで、次のコマンドを実行してSnyk CLIでコンテナをスキャンできます。

snyk container test <your-image>

PHP 7.4のベースイメージをスキャンすると、次のような結果が得られます。

php:7.4.30-cli-bullseyeベースイメージのターミナルスキャンで、脆弱性87件(重大2件、高4件、中2件、低79件)が検出されています。
Snykのコンテナスキャンにより、ベースイメージ内に87件の問題が見つかりました。

脆弱なコンテナを本番環境にデプロイしないよう、CI/CDパイプラインでコンテナスキャンを実行するのが理想的です。また、container monitorコマンドを使って、コンテナイメージのテスト情報をSnykに送信することもできます。そうすることで、Snykのダッシュボードに情報を表示し、イメージに新たな脆弱性が見つかった場合に通知を受け取れます。

snyk container monitor <your-image>

先ほどテストしたものと同じPHPイメージに対して実行すると、次のような結果になります。

PHP 7.4 CLIイメージ、対象OSのDebian 11、ベースイメージのアップグレードに関する推奨事項を示すDockerイメージの概要

簡単ですよね。しかも、これで終わりではありません。コンテナ化する前にPHPコードの安全性を確認するため、Snyk Codeも利用できます。

PHPアプリケーションのマニフェストファイルがあるフォルダーに移動し、以下のコマンドを実行すると結果を確認できます。

snyk code test

古いLaravelプロジェクトに対してSnyk Codeのテストを実行し、よくあるケースを確認できます。古くても動作しているPHPプロジェクトの脆弱性を検出するケースです。結果は次のとおりです。

SQLインジェクション、不適切な入力検証、リモートコード実行など、Laravelフレームワークの重大度の高い脆弱性を一覧表示するターミナル出力。

コンテナのモニタリングと同様に、PHPアプリのメインディレクトリでsnyk monitorを実行すれば、Snykにコードベースを監視させることもできます。すると、アプリケーションがSnykのダッシュボードに表示されます。

Laravelプロジェクトのcomposer.lockファイルで新たに公開された脆弱性を示すSnykのプロジェクトダッシュボード。

コンテナとコードの両方をセキュリティスキャンすることで、安全なコンテナとコードをリリースできます。

信頼できるコンテナイメージを使う

PHPコンテナを保護する方法の1つは、安全で信頼できるオンラインレジストリからイメージを取得することです。信頼できるレジストリでは、コンテナ環境からのデータ侵害につながる可能性がある、古いコードや悪意のあるコードを含むイメージが公開されている可能性が低くなります。たとえばDocker Hubには、Dockerが脆弱性を徹底的に検査し、提供元も検証した信頼性の高いイメージが多数掲載されており、ユーザーはそれらを利用できます。

ただし、Docker Hub上のすべてのイメージが信頼できるとは限りません。オンラインレジストリを利用する場合は、イメージの内容を確認し、潜在的なセキュリティ脆弱性がないか調べましょう。ホストシステムにダウンロードする前に、コンテナを脅かす悪意のあるコードが含まれていないかイメージをスキャンできます。この手順を確実に実施するには、Snykのようなセキュリティツールを開発ツールやワークフローに直接統合し、コンテナの潜在的な脆弱性を監視して修正できます。

スキャンに加えて、Docker Hub、Docker Verified publisherプログラム、Docker Official Imagesを利用することで、信頼できるコンテナイメージを使用できます。Docker Verified publisherプログラムは、ここから取得したイメージが信頼できるソースのものであることを検証し、ユーザーが偽のリポジトリから安全でないイメージを取得するのを防ぎます。

または、Docker Content Trustによって検証されたイメージを使用する方法もあります。Docker 1.8で導入されたDocker Content Trustは、イメージのデジタル署名と認証を強化する機能です。イメージ署名によってコンテナイメージのソースを検証し、改ざんされていないことを確認できます。また、検証済みイメージをユーザーがシステムに取り込む際に適用されるポリシーも定めます。

Docker Verified publisherまたはDocker Content Trustを通じてDockerの公式イメージを取得し、コンテナ環境を保護することに加えて、Snykを使ってコンテナを保護することも不可欠です。

PHP開発者が担うコンテナセキュリティ

PHPコンテナを潜在的なセキュリティ脅威から守るには、ビルドからデプロイ、実行時まで、アプリケーションのライフサイクル全体にわたって複数のセキュリティ手法を取り入れる必要があります。コンテナセキュリティに関するPHPアプリケーションのベストプラクティスに従うだけでなく、次のような自動化ツールを活用して、コンテナセキュリティの維持にSnykを役立てることができます。

  • GitHub ActionsやAWS Code Pipelineとのインテグレーションなど、CI/CDパイプラインでの自動セキュリティテスト

  • コンテナとソースコードの両方を対象とした、統合的なセキュリティインテリジェンス

  • Kubernetesクラスター内のコンテナを監視し、新たに発生した脆弱性や既存の脆弱性を検出するKubernetesインテグレーション

  • 開発者を第一に考えたアプローチで、自社のPHPコードに潜むセキュリティ問題を検出し、セキュリティの専門知識が豊富でなくても、開発者が問題を簡単に修正できるよう支援

Snyk Containerは、コンテナの脆弱性を包括的かつ効率的に特定・解決できる、コンテナ脆弱性管理ツールです。IDEに統合されたチェック、自動化されたCI/CDインテグレーション、ネイティブなGitスキャン、本番環境のテスト機能を備え、ソフトウェア開発ライフサイクル全体を通じて、Kubernetesのコンテナとワークロードを保護します。

開発者ファーストのコンテナセキュリティ

Snykは、コンテナイメージとKubernetesワークロードの脆弱性を検出し、自動的に修正します。

さらに、アプリケーションの開発中にVS-CodeやJetBrainsなどの開発ツールにセキュリティスキャンを統合すれば、脆弱性の種類や推奨される修正方法について、より多くの情報を得られます。Snykは、こうした脆弱性の特定にも役立ちます。

Snykは、コンテナセキュリティを脅かす脆弱性の特定も開発者に支援します。こうした問題を自動で修正することで生産性を高め、開発チームがコードの修正に費やす時間を減らし、アプリケーションの開発により多くの時間を充てられるようにします。今すぐ無料アカウントを作成しましょう。また、無料のオンラインPHPコードチェッカーツールを試して、Snyk Codeがコードのセキュリティと品質に関する問題をどのように分析するかをご確認ください。

続きを読む

blog feature snyk container custom base recommendations
Blog

Evo Agentic AppSecのご紹介:AI開発のスピードに対応するセキュリティ

AI駆動型開発のスピードに、従来のセキュリティワークフローは追いついていません。SnykのAgentic AppSecは、セキュリティエージェントが脆弱性を継続的に検出、修正、検証し、人が基準を定められるようにします。

blog feature ai violet
Blog

VulnBump:AIエージェントはビルドを壊さずに脆弱な依存関係を修正できるか?

VulnBumpは、実際の依存関係アップグレード307件を対象にAIエージェントをテストします。脆弱性が解消され、ビルドとテストが成功した場合にのみ、修正としてカウントされます。

Blog

フロンティアモデルは脆弱性を発見した。攻撃者だけがエクスプロイトチェーンを見つけた。

静的解析で欠陥は見つかりましたが、ライブ攻撃テストで侵害につながる連鎖を実証できたのは唯一でした。Evo COS、Claude Security、Claude Code Securityを比較します。