ユーザーが自分のサーバーに対して任意の信頼できないpythonコード( このようなビット )を実行できるようにする必要があるプロジェクトがあります。私は= pythonそして、システムにセキュリティホールやその他の脆弱性をもたらすような間違いを避けたいと思います。利用可能なベストプラクティス、推奨される読み物、または私に教えてくれる他の指針がありますか?サービスは使用可能ですが、悪用はできませんか?
これが私がこれまでに考えたことです:
__builtins__
exec
コンテキストから、os
のような潜在的に危険なパッケージの使用を禁止します。ユーザーは私が提供したパッケージのみを使用できます。exec
コンテキスト内で割り当てることができるメモリの総量を制限したいのですが、それが可能かどうかはわかりません。ストレートexec
に代わる方法はいくつかありますが、ここでどれが役立つかわかりません。
ast.NodeVisitor
安全でないオブジェクトにアクセスする試みをキャッチします。しかし、どのオブジェクトを禁止すべきですか?PyPy
またはコードをサンドボックスに類似したものを使用する。注:少なくとも1つ JavaScriptベースのインタープリターがあることを知っています。それは私のシナリオでは機能しません。
Pythonサンドボックス化はhardです。 Pythonは、本質的に複数のレベルで内省可能です。
これは、特定のタイプのファクトリーメソッドをそれらのタイプ自体から見つけ、new低レベルオブジェクトを構築して、直接実行されることも意味します無制限の通訳.
以下は、Pythonサンドボックスから抜け出すための創造的な方法を見つけるいくつかの例です。
Ned Batchelderは、 危険なeval()
が実際にどのように動作するかを示すデモから始まります ; eval()
は、Python式を実行するためによく使用されます;ワンライナーのプリミティブで単純なサンドボックスとして。
その後、彼は同じ原則を Python 3 に適用しようとし続け、最終的に いくつかの有用なポインタで を抜け出しました。
Pierre Bourdonは、同様の手法を使用して pythonシステムをhack-a-thonでハッキングします
基本的な考え方は、ベース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サンドボックス(ありそうもないことではありません)から抜け出すことができたとしても、攻撃者がアクセスするのは短期間であり、価値はありません。
TL; DR chroot/jailを使用して、権限のないカスタムユーザーとして実行します。
信頼できないコードを実行するためのベストプラクティスは、systemサンドボックスを介してコードを分離することです。最も安全のために:
また、chrootで安全に実行するための標準的な方法に従います。各呼び出しでchrootのファイルシステムを再構築することもできますが、これは特に偏執狂的です。通常は、chrootが実行されているファイルシステムをユーザーが変更できないようにします。
これを安全に行う方法はありません。
このようなことを安全に実行したい場合は、pythonの独自の実装を用意することから始める必要があります。これは完全に制御された環境で実行され、できればユーザーのブラウザで実行されます。 Jython(python for Java)から始めて、Javaアプレットとしてパッケージ化します。これはJavaサンドボックスで実行されるため、ユーザーのマシン、あなたのシステムはかなり安全でしょう。
Martijnが上で述べたように、これはPythonでは本当に非常に困難です。 Pythonは非常に内省的であるため、言語機能を制限することでそれが可能であるとは思わない。そして、あるバージョンのPythonで動作するサンドボックスを取得した場合、次のバージョンが壊せ。
標準のCPythonではなく PyPy を確認します。要するに、これはPythonの準拠した代替実装です。これにはいくつかの利点と明確な機能があり、そのうちの1つは言語機能を制限する代わりにシステムコールを置き換えることによるサンドボックス化です。
パフォーマンスがそれほど重要でない限り、JavaScriptサンドボックスに効果的に配置するBrythonでいつでも実行できます。