web-dev-qa-db-ja.com

信頼できないコードを実行するためのベストプラクティス

ユーザーが自分のサーバーに対して任意の信頼できないpythonコード( このようなビット )を実行できるようにする必要があるプロジェクトがあります。私は= pythonそして、システムにセキュリティホールやその他の脆弱性をもたらすような間違いを避けたいと思います。利用可能なベストプラクティス、推奨される読み物、または私に教えてくれる他の指針がありますか?サービスは使用可能ですが、悪用はできませんか?

これが私がこれまでに考えたことです:

  • 削除する __builtins__execコンテキストから、osのような潜在的に危険なパッケージの使用を禁止します。ユーザーは私が提供したパッケージのみを使用できます。
  • スレッドを使用して適切なタイムアウトを適用します。
  • execコンテキスト内で割り当てることができるメモリの総量を制限したいのですが、それが可能かどうかはわかりません。

ストレートexecに代わる方法はいくつかありますが、ここでどれが役立つかわかりません。

  • ast.NodeVisitor安全でないオブジェクトにアクセスする試みをキャッチします。しかし、どのオブジェクトを禁止すべきですか?
  • 入力内の二重下線を検索しています。 (上記のオプションよりも優雅ではありません)。
  • PyPyまたはコードをサンドボックスに類似したものを使用する。

注:少なくとも1つ JavaScriptベースのインタープリターがあることを知っています。それは私のシナリオでは機能しません。

31
p.s.w.g

Pythonサンドボックス化はhardです。 Pythonは、本質的に複数のレベルで内省可能です。

これは、特定のタイプのファクトリーメソッドをそれらのタイプ自体から見つけ、new低レベルオブジェクトを構築して、直接実行されることも意味します無制限の通訳.

以下は、Pythonサンドボックスから抜け出すための創造的な方法を見つけるいくつかの例です。

基本的な考え方は、ベースPythonタイプ、関数およびクラスを作成し、Pythonインタプリタを実行して任意のコードを実行することにより、シェルから抜け出す方法です。 (チェックされていない!)バイトコード。

同じことが、execステートメント(exec()関数Python 3))にも当てはまります。

だから、あなたはしたい:

  • Pythonコードのバイトコンパイルを厳密に制御するか、少なくともバイトコードを後処理して、アンダースコアで始まる名前へのアクセスを削除します。

    これには、Pythonインタープリターがどのように機能するか、およびPythonバイトコードが構造化される方法についての詳細な知識が必要です。コードオブジェクトはネストされています。モジュールのバイトコードは最上位のステートメントのみをカバーします、各関数とクラスは、独自のバイトコードシーケンスとメタデータで構成され、たとえば、ネストされた関数とクラスのotherバイトコードオブジェクトを含みます。

  • 使用できるwhitelistモジュールが必要です。慎重に。

    pythonモジュールには、otherモジュールへの参照が含まれています。osをインポートすると、ローカルosモジュールを参照するモジュール名前空間の名前os。これにより、攻撃者がサンドボックスから抜け出すのに役立つモジュールに攻撃者を導く可能性があります。pickleモジュール、たとえば、任意のコードオブジェクトを読み込むことができます。たとえば、ホワイトリストに登録されたモジュールのanyパスがpickleモジュールにつながる場合、まだ問題。

  • 時間の割り当てを厳密に制限する必要があります。最も去勢されたコードでさえも、永久に実行を試み、リソースを占有する可能性があります。

RestrictedPython を見てください。これは、厳密なバイトコード制御を提供しようとします。 RestrictedPython変換Pythonコードを何かに変換して、Python 2.3から2.7で許可される名前、モジュール、およびオブジェクトを制御できるようにします。

RestrictedPythonが目的に対して十分に安全かどうかは、実装するポリシーによって異なります。アンダースコアで始まる名前へのアクセスを許可せず、モジュールを厳密にホワイトリストに登録することから始めます。

私の意見では、本当に堅牢な唯一のオプションは、別の仮想マシンを使用することです。仮想マシンは、実行するたびに破棄する外部へのネットワークアクセスがないものです。新しい各スクリプトには、代わりに新しいVMが与えられます。これにより、コードがPythonサンドボックス(ありそうもないことではありません)から抜け出すことができたとしても、攻撃者がアクセスするのは短期間であり、価値はありません。

28
Martijn Pieters

TL; DR chroot/jailを使用して、権限のないカスタムユーザーとして実行します。

信頼できないコードを実行するためのベストプラクティスは、systemサンドボックスを介してコードを分離することです。最も安全のために:

  • Pythonのみのコンテナを作成し、それは依存関係とコンテナの依存関係です
  • 絶対に必要ではないすべてのデバイスなしでコンテナを作成します(つまり、ネットワークとストレージ)
  • メモリとプロセスの使用に制限があるコンテナを作成する
  • 実行ごとにコンテナを再作成します(または、少なくとも、各ユニークユーザーと最大期間で)
  • 必要最小限の権限を持つユーザーとして実行する
  • ファイルを書き込む権限のないユーザーとして実行する

また、chrootで安全に実行するための標準的な方法に従います。各呼び出しでchrootのファイルシステムを再構築することもできますが、これは特に偏執狂的です。通常は、chrootが実行されているファイルシステムをユーザーが変更できないようにします。

10
dietbuddha

これを安全に行う方法はありません。

このようなことを安全に実行したい場合は、pythonの独自の実装を用意することから始める必要があります。これは完全に制御された環境で実行され、できればユーザーのブラウザで実行されます。 Jython(python for Java)から始めて、Javaアプレットとしてパッケージ化します。これはJavaサンドボックスで実行されるため、ユーザーのマシン、あなたのシステムはかなり安全でしょう。

3
ddyer

Martijnが上で述べたように、これはPythonでは本当に非常に困難です。 Pythonは非常に内省的であるため、言語機能を制限することでそれが可能であるとは思わない。そして、あるバージョンのPythonで動作するサンドボックスを取得した場合、次のバージョンが壊せ。

標準のCPythonではなく PyPy を確認します。要するに、これはPythonの準拠した代替実装です。これにはいくつかの利点と明確な機能があり、そのうちの1つは言語機能を制限する代わりにシステムコールを置き換えることによるサンドボックス化です。

2
James

パフォーマンスがそれほど重要でない限り、JavaScriptサンドボックスに効果的に配置するBrythonでいつでも実行できます。

0
Big Ian