C ++プログラムでユーザースクリプトを安全にサンドボックス化する


8

私はC#で個人的なプロジェクトに取り組んでいますが、その目的は、ユーザーが他のユーザーが作成したスクリプトを実行して、そのスクリプトのアクセス許可を制限できるようにすることです。私のプログラムは、サードパーティのライブラリを使用してスクリプトをコンパイルし、.NETコードアクセスセキュリティメカニズムを使用してそれらをサンドボックス化し、ユーザーが付与したい権限のみがスクリプトにあることを確認します。

大まかに言って、私のセキュリティ要件は次のとおりです。

  • ユーザーは、信頼できないスクリプトのアクセスを、すべてのファイルシステムアクセスの禁止を含む、ファイルシステムの特定の部分のみに制限できる必要があります。
  • ユーザーは、信頼できないスクリプトのネットワーク接続を、すべてのネットワーク接続の禁止を含め、特定のIPアドレスまたはホスト名のみに制限できる必要があります。
  • ユーザースクリプトがホストアプリケーションをハングまたは終了させることができても問題ありませんが、ユーザースクリプトは権限の制限を回避できてはなりません(つまり、サービス拒否は問題ありませんが、違反は許されません)。

私は一種の個人的な演習として、C ++で同様のことをしようと考えています。明らかに、ユーザースクリプトがLuaのようなスクリプト言語で書かれている場合でも、ネイティブコードを直接実行すると、状況はさらに複雑になります。

最初に考えられるアプローチは、スクリプト環境の標準ライブラリ関数に独自のフックを挿入することです。たとえば、スクリプト言語がLuaの場合、io.openを通常に公開する代わりに、スクリプトの権限に対して引数をチェックするラッパーを公開してから、それらを元の実装に渡す必要があります。

このアプローチに対する私の懸念は、セキュリティを担当する自分自身のコードの量が大幅に増加することです。そのため、私が書いた潜在的なセキュリティの脆弱性があります。言い換えると、.NET CASを使用する場合、自分のサンドボックスコードを信頼する必要があるのではなく、Microsoftがサンドボックスコードでうまく機能したことを信頼できます。

私が知らない代替案はありますか?



Seccompのような@RobertHarvey Linuxコンテナー化手法は、通常、信頼できないコードを別のプロセスで実行する場合にのみ役立ちますが、プロセス内の分離には適用できません。もちろん、問題のかなり単純な解決策には、メインプログラムのサービスとして機能し、IPCメカニズムを介してのみ通信する個別のプロセスを含めることができます。Windowsに同様のOSレベルの分離機能があるかどうか。
amon

1
@amon:... Windows プロセスのようなものですか? もちろんです。
Robert Harvey

最初に、システムに最大の脆弱性をすでに導入しました:Foreign Code。他のすべてはその害を軽減する試みです。基本的に、その外部コードを安全に実行できるインタープリターを構築しています。移動し、あなたのブラッシュアップの解釈を理解することは、あなたが望む行動や相対的な安全性を強化するためにこれらのアイデアを適用します。次に、サンドボックスが安全であると想定せず、常に防御層を追加してください。
Kain0_0

1
@VojislavStojkovic JavaScriptエンジンだけを使用できませんか?デフォルトでは、これらのエンジンはファイルシステムにアクセスできません(ネットワークについては完全にはわかりませんが、確認できます)。QJSEngineがその一例です。また、これらのエンジンを使用すると、相互運用性のためにJavaScriptにカスタムC ++コード関数を提供できます。
RandomGuy

回答:


1

他の人が述べたように、外部コードの実行は、この種の実装に関する最大の問題です。Kain0_0のコメントが示唆するように、VMはホストマシンを危険にさらすことなく(過度に)外部コードの自由を維持するための最も適切な方法です。これは基本的にCircleCIのような継続的インテグレーションサービスが行うことです。

これにより、必要なすべての構成およびセキュリティ機能を備えたイメージをプルできるため、インターフェイスの実装がはるかに簡単になります。また、ホストでコードが実行されるかどうかを心配する必要もありません。

このため、私は次のようにします:

  • Dockerでカバーしたいユーザースクリプト環境のスナップショットを作成します(適切なセキュリティ構成でC#用の環境、Python用の環境など)

  • ユーザーの要求に応じて、コードトリガーを介してDocker関連のインスタンスを起動し、Dockerインスタンスのエントリポイントに外部スクリプトを挿入します。

  • コードはDockerインスタンスでユーザー権限で実行され、ファイルが書き込まれます。接続はあちこちで行われ、出力を取得して環境が破壊されます。

  • Dockerコンテナはプロセスとして実行されるため、かなり簡単に、つまり、特定の時間制限を超えた場合に終了できます。エラーがある場合は、すぐに終了できます。

基本的に、メインコードでDockerのユーザートリガー、エントリポイントインジェクション、および自動破棄ロジックを管理します。Dockerは、この種の操作のサンドボックス化を担当しています。


1
すばらしい答えです。答えに追加するものがあれば、すべての一般的なサンドボックスソリューションに、悪意のあるコードがそのサンドボックスから逃れることを可能にする多くの欠陥があったことになります。これはCAS(たとえばCVE-2015-2504)に当てはまり、Java(ブラウザJavaプラグインの悪用が多すぎてここにリストすることができない)にも当てはまります。Dockerにも脆弱性はありますが、特定の言語/フレームワークのレベルで実装されたものと比較して、攻撃対象領域がはるかに低いという印象があります。
Arseni Mourzenko
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.