著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。

序章

サンドボックスは、通常の操作中に対話する必要のないシステムの部分からプログラムまたはプロセスを分離することに焦点を当てたコンピューターセキュリティ技術です。 新しいプログラムが開始されると、それはそれが実行されるユーザーのすべての機能を備えています。 これらの能力は、プログラムがその機能を実行するために必要な能力をはるかに超えていることがよくあります。 これは、悪意のある攻撃者がプログラムを操作して、プログラムが通常は実行しないことを実行するために未使用の機能の一部にアクセスする場合に、セキュリティの問題を引き起こす可能性があります。

サンドボックス化の目的は、プログラムに必要な機能とリソースを正確に特定し、それ以外のすべてをブロックすることです。

ツールのシステム管理スイートsystemdは、プログラムとプロセスを開始、停止、および管理するために、ほとんどすべての主要なLinuxディストリビューションで使用されています。 開始するプロセスがホストシステムにアクセスする方法を制限する多くのサンドボックスオプションがあり、より安全になります。

このチュートリアルの目的は、可能な限り厳密なサンドボックス環境を作成することではなく、推奨され、簡単に有効にできる設定を使用して、システムをより安全にすることです。

このチュートリアルでは、Ubuntu 20.04でsystemdのサンドボックス技術を使用して、これらの技術を実装およびテストするための効率的なワークフローを実現する方法の実践的なデモンストレーションを実行します。 systemdを使用するLinuxシステムで実行されるプロセスはすべて、これらの手法を使用してより安全にすることができます。

前提条件

このガイドを開始するには、次のものが必要です。

ステップ1—lighttpdをインストールする

このチュートリアルでは、 lighttpdWebサーバーをサンドボックス化します。 lighttpdは、他のソフトウェアよりも安全性が低いために選択されませんでしたが、サンドボックス化が容易な単一の機能を備えた小さなプログラムであるためです。 これにより、学習アプリケーションに最適です。

システムを更新して開始しましょう。

  1. sudo apt update

yと入力する前に、システムでアップグレードされるパッケージを確認してください。

  1. sudo apt upgrade

次にlighttpdをインストールします。

  1. sudo apt install lighttpd

このインストールプロセスにより、lighttpdのsystemdサービスファイルが自動的にインストールされて有効になります。 これにより、システムの再起動時にlighttpdが起動します。

システムにlighttpdをインストールして実行したので、サンドボックス化を開始するときに使用するsystemdツールについて理解します。

ステップ2—システムの準備

このステップでは、使用するsystemdコマンドに精通し、プロセスを効率的にサンドボックス化できるようにシステムを準備します。

systemdは、それぞれ異なる名前を持つ一連のツールの包括的な名前です。 使用するのはsystemctljournalctlの2つです。 systemctlはプロセスとそのサービスファイルを管理し、journalctlはシステムログと対話します。

systemdは、サービスファイルを使用して、プロセスの管理方法を定義します。 systemdは、ファイルシステム内のいくつかの場所からこれらのファイルをロードします。 次のコマンドは、アクティブなサービスファイルの場所を表示し、使用中のオーバーライドを表示します。

  1. sudo systemctl cat process.service

processを作業中のプロセスに置き換える必要があります。 ここではlighttpdが使用されています:

  1. sudo systemctl cat lighttpd.service

これは前のコマンドからの出力です:

Output
# /lib/systemd/system/lighttpd.service [Unit] Description=Lighttpd Daemon After=network-online.target [Service] Type=simple PIDFile=/run/lighttpd.pid ExecStartPre=/usr/sbin/lighttpd -tt -f /etc/lighttpd/lighttpd.conf ExecStart=/usr/sbin/lighttpd -D -f /etc/lighttpd/lighttpd.conf ExecReload=/bin/kill -USR1 $MAINPID Restart=on-failure [Install] WantedBy=multi-user.target

この出力は、サービスファイルが/lib/systemd/system/lighttpd.serviceにあり、使用中のオーバーライドオプションがないことを示しています。 オーバーライドオプションは、ベースサービスファイルに追加または変更します。 専用のオーバーライドファイルを使用してlighttpdをサンドボックス化するためにオーバーライドを使用します。

オーバーライドファイルは/etc/systemd/system/process.service.d/override.confにあります。 systemdには専用のeditコマンドがあり、正しい場所にオーバーライドファイルを作成し、エディターを保存して終了した後にsystemctl daemon-reloadを実行します。 systemctl daemon-reloadは、作成した新しい構成を使用するようにsystemdに指示します。

systemdeditコマンドの形式は次のとおりです。

  1. sudo systemctl edit process.service

このコマンドを実行すると、systemdは通常デフォルトのCLIエディターを選択しますが、常にそうであるとは限らず、viまたはedにいることもあります。 SYSTEMD_EDITORシェル変数を設定することにより、systemdが使用するエディターを構成できます。

~/.bashrcファイルに行を追加して、このシェル変数を設定します。 このファイルをテキストエディタで開きます。

  1. nano ~/.bashrc

そして、次の行を追加します。

〜/ .bashrc
export SYSTEMD_EDITOR=editor

editorをお好みのCLIエディターに変更します。 nanoエディターを使用するために設定された行は次のとおりです。

〜/ .bashrc
export SYSTEMD_EDITOR=nano

echoコマンドを使用してログアウトし、再度ログインした後、これが設定されていることを確認します。

  1. echo $SYSTEMD_EDITOR

このコマンドは、設定したエディターの名前を出力します。

SYSTEMD_EDITORシェル変数はユーザーのシェルでのみ設定され、sudoによって開かれるrootのシェルでは設定されません。 この変数をrootのシェルに渡すには、sudo -Eを使用してsystemctl editを呼び出します。

  1. sudo -E systemctl edit process.service

最後の推奨事項は、変更によって発生したエラーを表示することにより、サンドボックスのデバッグを容易にします。 これらのエラーは、journalctlコマンドでアクセスされるシステムログに記録されます。

サンドボックス化中に、サンドボックス化しようとしているプロセスを中断する多くの変更を加えます。 そのため、2つ目の端末を開いて、システムログの追跡専用にすることをお勧めします。 これにより、システムログを再度開く時間を節約できます。

次のコマンドを実行して、2番目の端末のシステムログを追跡します。

  1. sudo journalctl -f -u process.service
  • -f:システムログを追跡または追跡して、新しい行がすぐに表示されるようにします。
  • -u process.service:サンドボックス化するprocessのログ行のみを表示します。

以下は、lighttpdのエラーのみを出力するために実行する必要があるものです。

  1. sudo journalctl -f -u lighttpd.service

次に、override.confファイルの編集を開始し、lighttpdのサンドボックス化を開始します。

ステップ3—ユーザーとグループを強制する

このステップでは、lighttpdを実行するroot以外のユーザーを設定します。

デフォルト設定では、lighttpdは root ユーザーとして実行を開始し、www-dataユーザーとグループに変更します。 これは問題です。lighttpdがrootとして実行されている間は、rootが実行できることは何でも実行できるからです。

systemdは、root以外のユーザーとしてプロセスを開始および実行する機能を提供するため、この問題を回避できます。

最初のターミナルセッションに戻り、次のコマンドを実行してオーバーライドファイルの編集を開始します。

  1. sudo -E systemctl edit lighttpd.service

ここで、次の行を追加します。

lighttpdオーバーライドファイル
[Service]
User=www-data
Group=www-data
  • [Service]:次のオプションを[Service]セクションに適用する必要があることをsystemdに通知します。
  • User=www-data:プロセスを開始するユーザーを定義します。
  • Group=www-data:プロセスを開始するグループを定義します。

次に、エディタを保存して終了し、次のコマンドでlighttpdを再起動します。

  1. sudo systemctl restart lighttpd.service

root権限を使用してルートが所有する場所にPIDファイルを書き込んでいたため、lighttpdを起動できません。 www-data ユーザーは、rootが所有するディレクトリに書き込むことができません。 この問題は、2番目のターミナルセッションに表示されるシステムログに示されます。

journalctl error message
Aug 29 11:37:35 systemd lighttpd[7097]: 2020-08-29 11:37:35: (server.c.1233) opening pid-file failed: /run/lighttpd.pid Permission denied

この問題の解決は、サンドボックス化のプロセスに従います。

  1. サンドボックス制限を実装します。
  2. プロセスを再開し、エラーを確認します。
  3. エラーを修正します。

次に、このセクションで設定したユーザーとグループの制限を適用しながら、PIDファイルの問題を解決します。

ステップ4—PIDファイルの管理

PIDファイルは、実行中のプロセスのPIDまたはプロセス識別番号を含むファイルです。 lighttpdのような長時間実行されるプログラムは、それらを使用して独自のプロセスを管理します。 前のセクションで発生した問題は、/run/root によって所有されているため、lighttpdがPIDファイルを/run/lighttpd.pidに書き込めないことでした。

systemdには、この問題に対するRuntimeDirectoryオプションがあります。これを使用して、lighttpdにPIDファイルを書き込める場所を指定します。

RuntimeDirectoryオプションを使用すると、systemdがlighttpdを起動したときにステップ3で設定したユーザーとグループで作成される/run/の下のディレクトリを指定できます。 lighttpdは、 rootの権限を必要とせずに、そのPIDをこのディレクトリに書き込むことができます。

まず、ステップ3 で使用したのと同じコマンドを使用して、オーバーライドファイルを開いて編集します。

  1. sudo -E systemctl edit lighttpd.service

次に、オーバーライドファイルにすでに追加した2行の下に次の行を追加します。

lighttpdオーバーライドファイル
RuntimeDirectory=lighttpd

エディターを保存して終了します。

RuntimeDirectoryを使用してディレクトリへのフルパスを追加するのではなく、/run/の下のディレクトリの名前のみを追加します。 この場合、systemdが作成するディレクトリは/run/lighttpd/です。

次に、/run/ではなく新しいディレクトリ/run/lighttpd/にPIDファイルを書き込むようにlighttpdを設定する必要があります。

テキストエディタでlighttpdの設定ファイルを開きます。

  1. sudo nano /etc/lighttpd/lighttpd.conf

次の行を変更します。

/etc/lighttpd/lighttpd.conf
server.pid-file             = "/run/lighttpd.pid"

に:

/etc/lighttpd/lighttpd.conf
server.pid-file             = "/run/lighttpd/lighttpd.pid"

エディターを保存して終了します。

ここで、lighttpdを再起動します。

  1. sudo systemctl restart lighttpd.service

rootの機能の1つを必要とする何かを実行できないため、起動しません。 次に、この新しい問題を解決します。

ステップ5—ルートの機能を借用する

システムログの次の行は、lighttpdの起動を停止した問題を説明しています。

journalctl error message
Aug 29 12:07:22 systemd lighttpd[7220]: 2020-08-29 12:07:22: (network.c.311) can't bind to socket: 0.0.0.0:80 Permission denied

root のみが、番号1024未満のネットワークポートを開くことができます。 lighttpdはHTTPポート80を開こうとしていますが、 www-data ユーザーがそれを行うことができないため、拒否されています。

この問題は、lighttpdプロセスに rootのパワーのごく一部、つまり1024より下のポートを開くことで解決されます。

rootの「力」は、「能力」と呼ばれる能力に分けられます。 root ユーザーはすべての機能を備えているため、何でもできます。 rootのパワーアップを機能に分割することは、それらを非rootプロセスに個別に与えることができることを意味します。 これにより、そのプロセスは完全な root ユーザーを必要とする何かを実行できますが、通常のユーザーはrootの機能の1つを使用できるようになります。

プロセスにrootの機能の1つ以上を提供するsystemdオプションは、AmbientCapabilitiesオプションです。

オーバーライドファイルを開きます。

  1. sudo -E systemctl edit lighttpd.service

次に、すでに追加した行の下に次の行を追加します。

lighttpdオーバーライドファイル
AmbientCapabilities=CAP_NET_BIND_SERVICE

CAP_NET_BIND_SERVICE機能を使用すると、プロセスは1024の下のポートを開くことができます。

ファイルを保存して終了します。

これでlighttpdを起動できるようになります。

これで、デフォルト設定よりも安全にしたlighttpdWebサーバーが機能するようになりました。 systemdが提供するサンドボックスオプションには、ターゲットプロセスをさらに安全にするために使用できるものがあります。 次のセクションでは、これらのいくつかについて説明します。

次のステップでは、lighttpdがファイルシステムでアクセスできるものを制限します。

ステップ6—ファイルシステムをロックダウンする

lighttpdプロセスはwww-dataユーザーとして実行されるため、www-dataが読み取りおよび書き込みを許可されているシステム上の任意のファイルにアクセスできます。 www-data の場合、それほど多くはありませんが、lighttpdが必要とする以上のものです。

最初で最も簡単なサンドボックス設定は、ProtectHomeオプションです。 このオプションは、プロセスが/home/の下にあるものに対して読み取りまたは書き込みを行うのを停止します。 lighttpdは/home/の下にあるものにアクセスする必要がないため、これを実装すると、lighttpdに影響を与えることなくすべてのプライベートファイルを保護できます。

オーバーライドファイルを開きます。

  1. sudo -E systemctl edit lighttpd.service

次に、ファイルの最後に次の行を追加します。

lighttpdオーバーライドファイル
ProtectHome=true

エディターを保存して終了し、lighttpdを再起動して、次のコマンドで期待どおりに機能していることを確認します。

  1. sudo systemctl restart lighttpd.service

/home/を保護しましたが、それでもファイルシステムの残りの部分は残ります。 これは、プロセスがファイルシステムの一部に書き込むのを停止するProtectSystemオプションで処理されます。

ProtectSystemオプションには、保護レベルを上げる3つの設定があります。 それらは次のとおりです。

  • true:次のディレクトリを読み取り専用に設定します:
      / usr / / boot / / efi /
  • full:次のディレクトリを読み取り専用に設定します:
      / usr / / boot / / efi / / etc /
  • strict:次のディレクトリを読み取り専用に設定します。
      ファイルシステム全体

より高いレベルの保護はより安全であるため、オーバーライドファイルに次の行を追加してProtectSystemオプションをstrictに設定します。

lighttpdオーバーライドファイル
ProtectSystem=strict

エディターを保存して終了し、次のコマンドでlighttpdを再起動します。

  1. sudo systemctl restart lighttpd.service

lighttpdは、ログファイルを/var/log/lighttpd/に書き込む必要があり、strict設定でそれが禁止されているため、起動できません。 システムログの次の行は、問題を示しています。

journalctl error message
Aug 29 12:44:41 systemd lighttpd[7417]: 2020-08-29 12:44:41: (server.c.752) opening errorlog '/var/log/lighttpd/error.log' failed: Read-only file system

この問題は、LogsDirectoryオプションを指定したsystemdで予期されていました。 プロセスがログを書き込むことを許可されている/var/log/の下のディレクトリの名前を取ります。

最初のターミナルセッションでオーバーライドファイルを再度開きます。

  1. sudo -E systemctl edit lighttpd.service

lighttpdログディレクトリは/var/log/lighttpd/なので、オーバーライドファイルの最後に次の行を追加します。

lighttpdオーバーライドファイル
LogsDirectory=lighttpd

エディターを保存して終了し、lighttpdを再起動します。

  1. sudo systemctl restart lighttpd.service

これでlighttpdを起動して実行できるようになります。

注: lighttpd以外のプロセスをサンドボックス化し、プロセスが/var/log/の外部の特定のディレクトリへの書き込みアクセスを許可する場合は、ReadWritePathsオプションを使用します。

次のステップでは、lighttpdプロセスがシステムの他の部分と対話する方法を制限するために、許可されているシステムコールを制限します。

ステップ7—システムコールを制限する

システムコールは、プログラムがカーネルに何かを要求する方法です。 システムコールの数は非常に多く、ファイルの読み取り、書き込み、削除などのアクション、ファイルシステムのマウント、スポーンプロセス、再起動などのハードウェア関連のタスクが含まれます。

systemdは、lighttpdのようなプロセスが通常使用し、使用しないコールを除外するシステムコールのグループを作成しました。 ブロックされたシステムコールは、ファイルシステムのマウントやシステムの再起動などですが、lighttpdでは実行する必要はありません。

まず、オーバーライドファイルを開きます。

  1. sudo -E systemctl edit lighttpd.service

ファイルの最後に次の行を追加して、SystemCallFilterオプションを使用して@system-serviceグループを設定します。

lighttpdオーバーライドファイル
SystemCallFilter=@system-service

エディターを保存して終了し、lighttpdを再起動します。

  1. sudo systemctl restart lighttpd.service

次のセクションでは、残りの推奨サンドボックスオプションを適用します。

ステップ8—追加オプションの実装

systemdのドキュメントでは、lighttpdのような長時間実行されるネットワークプロセスに対して次のオプションを有効にすることを推奨しています。 これらの設定はすべてオプションですが、それぞれがサンドボックス化するプロセスをより安全にするため、可能であれば使用する必要があります。

これらのオプションを一度に1つずつ有効にし、各オプションの後でプロセスを再開する必要があります。 それらをすべて一度に追加すると、問題のデバッグははるかに困難になります。

以下の推奨オプションには、それらの機能の簡単な説明が付いています。 これらの行を、すでに追加した行の下のオーバーライドファイルに追加します。

lighttpdオーバーライドファイル
NoNewPrivileges=true

このオプションは、サンドボックス化されたプロセスとその子が新しい特権を取得するのを停止します。

lighttpdオーバーライドファイル
ProtectKernelTunables=true

このオプションは、プロセスがカーネル変数を変更するのを停止します。

lighttpdオーバーライドファイル
ProtectKernelModules=true

このオプションは、プロセスがカーネルモジュールをロードまたはアンロードするのを停止します。

lighttpdオーバーライドファイル
ProtectKernelLogs=true

このオプションは、プロセスがカーネルログに直接読み書きするのを停止します。 ログメッセージを記録するには、システムログアプリケーションを使用する必要があります。

lighttpdオーバーライドファイル
ProtectControlGroups=true

このオプションは、プロセスによるシステム制御グループの変更を停止します。

lighttpdオーバーライドファイル
MemoryDenyWriteExecute=true

このオプションは、システムのメモリで実行されているコードをプロセスが変更するのを停止します。

lighttpdオーバーライドファイル
RestrictSUIDSGID=true

このオプションは、プロセスがファイルまたはディレクトリにset-user-ID(SUID)またはset-group-ID(SGID)を設定するのを停止します。 この機能は、特権を高めるために悪用される可能性があります。

lighttpdオーバーライドファイル
KeyringMode=private

このオプションは、プロセスが同じユーザーとして実行されている他のプロセスのカーネルキーリングにアクセスするのを停止します。

lighttpdオーバーライドファイル
ProtectClock=true

このオプションは、プロセスがハードウェアおよびソフトウェアのシステムクロックを変更するのを停止します。

lighttpdオーバーライドファイル
RestrictRealtime=true

このオプションは、CPUを過負荷にするために悪用される可能性のあるリアルタイムスケジューリングをプロセスが有効にするのを停止します。

lighttpdオーバーライドファイル
PrivateDevices=true

このオプションは、プロセスがストレージデバイスやUSBデバイスなどのシステムに接続されている物理デバイスにアクセスするのを停止します。

lighttpdオーバーライドファイル
PrivateTmp=true

このオプションは、プロセスにプライベート/tmp/および/var/tmp/ディレクトリの使用を強制します。 これにより、プロセスは、これらの共有システムディレクトリに保存されている他のプログラムの一時ファイルを読み取ることができなくなります。

lighttpdオーバーライドファイル
ProtectHostname=true

このオプションは、プロセスがシステムのホスト名を変更するのを停止します。

サンドボックス化したプロセスは、デフォルト構成よりもはるかに安全になりました。 これで、これらの手法を使用して、Linuxシステムで保護する必要のある他のプロセスに使用できます。

結論

この記事では、systemdサンドボックスオプションを使用してlighttpdプログラムをより安全にしました。 これらの手法は、systemdが管理する任意のプロセスで使用できるため、システムのセキュリティを継続的に向上させることができます。

サンドボックスおよびその他のセキュリティオプションの全リストは、systemdのオンラインドキュメントにあります。 また、DigitalOceanコミュニティでセキュリティトピックをさらにチェックしてください。