アプリケーションが最初からより低いレベルで実行できる場合、セキュリティのためにサンドボックスをchrootするのはなぜですか?


14

私はCでHTTPサーバーデーモンを書いています(理由があります)、systemdユニットファイルで管理しています。

私は20年前、1995年頃に設計されたアプリケーションを書き直しています。そして、彼らが使用するシステムは、chrootしてからsetuidするというもので、標準的な手順です。

さて、私の以前の仕事では、通常のポリシーでは、ルートとしてプロセスを実行することは決してありませんでした。そのためのユーザー/グループを作成し、そこから実行します。もちろん、システムはルートとしていくつかのことを実行しましたが、ルートにならずにすべてのビジネスロジック処理を実現できました。

HTTPデーモンの場合、アプリケーション内でchrootしなければ、rootなしで実行できます。アプリケーションをrootとして実行することは決して安全ではありませんか?

最初からmydaemon-userとして実行する方が安全ではありませんか?root、chrooting、setuidでmydaemon-userで起動する代わりに?


3
ポート80または443を使用するには、rootとして実行する必要があります。それ以外の場合は、Tomcatおよび他のwebapp / web-serverソフトウェアが行うことを実行し、より高いポート(8080、9090など)で実行してから、いずれかを使用できますapache / nginxを使用して、Webサーバーソフトウェアへの接続をプロキシするか、システムのファイアウォールを使用して、ポート80からWebサーバーにトラフィックをNAT /転送します。ポート80または443が必要ない場合、または接続をプロキシまたは転送できる場合、その後、rootとして、chrootなどで実行する必要はありません。
SnakeDoc

3
Linuxの@SnakeDocはもはや正しくありません。に感謝しcapabilities(7)ます。
0xC0000022L

@SnakeDocを使用できauthbindだけでなく
アブドゥルAhad

回答:


27

他の人があなたのポイントを逃したようです。これは、変更されたルートを使用する理由ではなく、もちろんすでに知っていますが、デーモンの制限の下に実行することを明確に知っているときに他にできることはありません特権のないユーザーアカウント。しかし、アプリケーション内でこのようなことを行う理由。実際には、かなり理由のある例があります。

httpdDaniel J. Bernsteinのpublicfileパッケージのdæmonプログラムの設計を検討してください。最初に行うことは、コマンド引数で使用するように指示されたルートディレクトリにルートを変更し、2つの環境変数で渡される特権のないユーザーIDとグループIDに特権をドロップします。

Dæmon管理ツールセットには、ルートディレクトリの変更、特権のないユーザーおよびグループIDへのドロップなどの専用ツールがあります。Gerrit Papeのrunitにはがありchpstます。私のnoshツールセットにはとがchrootありsetuidgid-fromenvます。Laurent Bercotのs6にはとがs6-chrootありs6-setuidgidます。ウェインマーシャルのパープにはとがruntoolありrunuidます。などなど。実際、それらはすべて、M。Bernstein独自のdaemontoolsツールセットをsetuidgid前件として持っています。

そのhttpdような専用ツールから機能を抽出し、使用できると思うでしょう。次に、あなたが想像するように、いいえに、サーバープログラムの部分もスーパーユーザー特権で実行さ。

問題は、直接的な結果として、変更されたルートをセットアップするためにかなり多くの作業を行う必要があり、これが新しい問題を露呈することです。

Bernsteinの現状httpdでは、ルートディレクトリツリーにあるファイルとディレクトリは、世界に公開されるものだけです。ツリーには何もありません。また、理由はない任意の実行可能プログラムのイメージファイルはそのツリー内に存在します。

しかし、チェーンローディングプログラム(またはにsystemd)へのルートディレクトリの変更を移動し、突然のプログラム、画像ファイルhttpd、任意の共有ライブラリを、それをロードし、特別なファイルであること/etc/runおよび/devプログラムローダーやCライブラリのアクセスをランタイムこと(あなたがあれば、非常に驚くかもしれプログラム初期化中truss/ straceCまたはC ++プログラム)、また、変更されたルートに存在しなければなりません。それ以外の場合httpdは、チェーン化できず、ロード/実行されません。

これはHTTP(S)コンテンツサーバーであることを忘れないでください。変更されたルートにある(世界で読み取り可能な)ファイルを提供する可能性があります。これには、共有ライブラリ、プログラムローダー、オペレーティングシステムのさまざまなローダー/ CRTL構成ファイルのコピーなどが含まれます。また、コンテンツサーバーが何らかの(偶発的な)書き込みアクセスを持っている場合、侵害されたサーバーは、httpdそれ自体のプログラムイメージ、またはシステムのプログラムローダーへの書き込みアクセスを取得する可能性があります。(あなたが今の二つの平行なセットを持っていることを忘れないでください/usr/lib/etc/run、および/dev安全に保つためにディレクトリを。)

これはどれも、 httpdルートを変更して特権自体をドロップ。

そのため、少量の特権コードを使用して取引しました。これはかなり簡単に監査でき、httpdプログラムの開始直後に実行され、スーパーユーザー特権で実行されます。変更されたルート内のファイルおよびディレクトリの攻撃対象領域を大幅に拡大したため。

これが、サービスプログラムの外部ですべてを行うほど単純ではない理由です。

それでも、これはそれhttpd自体の最低限の機能であることに注意してください。最初の場所でこれらの環境変数の中に入れて、ユーザIDとグループIDのためのオペレーティング・システムのアカウントデータベースに、ルックなど、物事を行うコードのすべてがある外部のhttpdようなシンプルなスタンドアロン監査可能なコマンドで、プログラムenvuidgid。(そして、もちろん、それは、関連するTCPポート(複数可)をリッスンするか、接続、などのコマンドのドメインであること、これらの受諾するためのコードを全く含まないので、UCSPIツールですtcpservertcp-socket-listentcp-socket-accepts6-tcpserver4-socketbinders6-tcpserver4d、などを。)

参考文献


+1、有罪として有罪。タイトルと最後の段落があいまいであることがわかりました。正しい場合は、その点を見逃しました。この答えは非常に実用的な解釈を提供します。個人的には、このようにchroot環境を構築することは余分な労力であり、ほとんどの人が避けたいことであることを明示的に指摘します。しかし、ここでの2つのセキュリティポイントはすでに十分に作成されています。
sourcejedi

覚えておくべきもう1つの点は、サーバーがネットワークトラフィックを処理する前に特権をドロップした場合、特権コードはリモートからのエクスプロイトにさらされないことです。
カスペルド

5

あなたの質問の多くの詳細は、avahi-daemon私が最近見たに等しく適用できると思います。(ただし、別の詳細を見逃したかもしれません)。chrootでavahi-daemonを実行すると、avahi-daemonが危険にさらされた場合に多くの利点があります。これらには以下が含まれます。

  1. ユーザーのホームディレクトリを読み取ったり、個人情報を盗んだりすることはできません。
  2. / tmpに書き込むことで他のプログラムのバグを悪用することはできません。このようなバグには少なくとも1つのカテゴリがあります。例:https : //www.google.co.uk/search? q = tmp+race+security+ bug
  3. chrootの外部にあるUNIXソケットファイルを開くことはできません。他のデーモンがメッセージをリッスンおよび読み取りしている可能性があります。

ポイント3は、dbusなどを使用していない場合に特に便利です。avahi-daemonはdbusを使用するため、chroot内からでもシステムdbusにアクセスできるようにします。システムdbusでメッセージを送信する機能が必要ない場合、その機能を拒否することは非常に優れたセキュリティ機能です。

systemdユニットファイルで管理する

avahi-daemonが書き直された場合、セキュリティのためにsystemdに依存する可能性があることに注意してくださいProtectHome。chrootでは保証されない追加の保護とともに、これらの保護を追加のレイヤーとして追加するavahi-daemonへの変更を提案しました。ここで提案したオプションの完全なリストを見ることができます:

https://github.com/lathiat/avahi/pull/181/commits/67a7b10049c58d6afeebdc64ffd2023c5a93d49a

avahi-daemonがchroot自体を使用しなかった場合に使用できる制限がさらにあるようです。その一部はコミットメッセージに記載されています。しかし、これがどれだけ当てはまるのかわかりません。

私が使用した保護は、デーモンがUNIXソケットファイルを開くことを制限していないことに注意してください(上記のポイント3)。

別のアプローチは、SELinuxを使用することです。ただし、Linuxディストリビューションのサブセットにアプリケーションを結び付けることになるでしょう。ここでSELinuxを積極的に考えた理由は、SELinuxがプロセスがdbus上で持つアクセスをきめ細かく制限するためです。たとえば、systemdメッセージを送信できるようにするために必要なバス名のリストに含まれていないことをしばしば期待できると思います:-)。

「chroot / setuid / umask / ...よりも安全なsystemdサンドボックスを使用する場合、私は疑問に思っていました。」

要約:なぜ両方ではないのですか?上記を少しデコードしてみましょう:-)。

ポイント3について考えた場合、chrootを使用するとより多くの制限が提供されます。ProtectHome =とその友人は、chrootほど制限的であろうとさえしません。(たとえば、名前付きsystemdオプションblacklistsはどれも、/rununixソケットファイルを配置する傾向があります)。

chrootは、ファイルシステムへのアクセスを制限することは非常に強力ですが、Linux上のすべてがファイルであるとは限らないことを示しています:-)。ファイルではない他のものを制限できるsystemdオプションがあります。これは、プログラムが危険にさらされている場合に役立ちます。利用可能なカーネル機能を減らして、脆弱性を悪用しようとする可能性があります。たとえば、avahi-daemonはbluetoothソケットを必要とせず、Webサーバーも:-)。したがって、AF_BLUETOOTHアドレスファミリへのアクセスを許可しないでください。RestrictAddressFamilies=オプションを使用して、AF_INET、AF_INET6、および場合によってはAF_UNIXをホワイトリストに追加してください。

使用する各オプションのドキュメントをお読みください。一部のオプションは他のオプションと組み合わせてより効果的であり、一部のオプションはすべてのCPUアーキテクチャで利用できるわけではありません。(CPUが悪いからではなく、そのCPUのLinuxポートがうまく設計されていなかったからです。私は思う)。

(ここに一般的な原則があります。拒否したいものではなく、許可したいもののリストを書くことができればより安全です。chrootを定義することで、アクセスが許可されたファイルのリストが得られ、あなたがブロックしたいと言っているよりも/home)。

原則として、setuid()の前に同じ制限をすべて自分で適用できます。systemdからコピーできるのは、すべてコードだけです。ただし、systemdユニットオプションは非常に記述しやすく、標準形式であるため、読みやすく、確認しやすいものでなければなりません。

そのman systemd.execため、ターゲットプラットフォームのサンドボックスセクションを読むことを強くお勧めします。しかし、可能な限り最も安全な設計が必要な場合は、プログラムでも同様に試してみるchroot(そして、root特権を落とす)ことを恐れません。ここにはトレードオフがあります。を使用すると、設計全体にいくつかの制約が課せられます。chrootを使用する設計が既にあり、必要なことを実行しているようであれば、それは非常に素晴らしいことです。chroot


特にsystemdの提案については+1。
mattdm

スタックオーバーフローが複数の回答を許可した場合、私はウルの回答からかなり多くを学びました。ウルも受け入れます。より安全なサンドボックスsystemdに使用している場合、私は、思っていたのchroot /のsetuid / umask値/ ...
MUR

@murあなたがそれを気に入ってくれてうれしい:)。それは私の答えに対する非常に自然な反応です。そこで、あなたの質問に答えてみようと、もう一度更新しました。
sourcejedi

1

systemdに依存できる場合は、sandboxをsystemdに任せる方が確かに安全です(そしてもっと簡単です!)。(もちろん、アプリケーションはsystemdによってサンドボックス化されて起動されたかどうかを検出でき、まだルートである場合はサンドボックス自体を検出できます。)説明するサービスに相当するものは次のようになります。

[Service]
ExecStart=/usr/local/bin/mydaemon
User=mydaemon-user
RootDirectory=...

しかし、そこで停止する必要はありません。systemdは、他にも多くのサンドボックス化を行うことができます。以下に例を示します。

[Service]
# allocate separate /tmp and /var/tmp for the service
PrivateTmp=yes
# mount / (except for some subdirectories) read-only
ProtectSystem=strict
# empty /home, /root
ProtectHome=yes
# disable setuid and other privilege escalation mechanisms
NoNewPrivileges=yes
# separate network namespace with only loopback device
PrivateNetwork=yes
# only unix domain sockets (no inet, inet6, netlink, …)
RestrictAddressFamilies=AF_UNIX

man 5 systemd.execより多くのディレクティブと詳細な説明を参照してください。デーモンをソケットアクティベート可能(man 5 systemd.socket)にすると、ネットワーク関連のオプションを使用することさえできます:サービスの外部への唯一のリンクはsystemdから受信したネットワークソケットになり、他のものには接続できなくなります。一部のポートでのみリッスンし、他のサーバーに接続する必要がない単純なサーバーの場合、これは便利です。(RootDirectory私の意見では、ファイルシステム関連のオプションも廃止される可能性があるため、必要なすべてのバイナリとライブラリで新しいルートディレクトリを設定する必要はもうないでしょう。)

新しいバージョンのsystemd(v232以降)もサポートDynamicUser=yesしています。この場合、systemdは、サービスのランタイムに対してのみ自動的にサービスユーザーを割り当てます。この手段はあなたがサービスのための恒久的なユーザーを登録する必要があり、その以外の任意のファイルシステムの場所に書き込めません長いサービスなどとして罰金の作品はありませんStateDirectoryLogsDirectoryCacheDirectory(あなたはまた、ユニットファイルで宣言することができました-を参照してくださいman 5 systemd.exec–そして、どのsystemdが管理し、それらを動的ユーザーに正しく割り当てるように注意してください)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.