私は純粋なPythonでWebゲームを開発しています。より動的なゲームコンテンツを可能にするために、いくつかの簡単なスクリプトを使用できるようにしたいと考えています。特権ユーザーは、ゲームコンテンツをライブで追加できます。
スクリプト言語をPythonにできればいいのですが。ただし、悪意のあるユーザーが悪い結果をもたらす可能性があるため、ゲームを実行する環境にアクセスして実行することはできません。サンドボックス化されたPythonを純粋なPythonで実行することは可能ですか?
更新:実際には、true Pythonサポートは過剰なものになるため、Pythonic構文を使用した単純なスクリプト言語が最適です。
Pythonicスクリプトインタープリターがない場合、純粋なPythonで記述できる他のオープンソーススクリプトインタープリターはありますか?要件は、変数、基本的な条件、および関数呼び出しのサポートです(定義)。
これは実に重要なことです。
Pythonをサンドボックス化するには2つの方法があります。 1つは、制限された環境(つまり、非常に少数のグローバルなど)を作成し、この環境内にコードをexec
作成することです。これはメッサが示唆していることです。それは素晴らしいことですが、サンドボックスから抜け出し、トラブルを引き起こす方法はたくさんあります。 1年ほど前にPython-devでこれに関するスレッドがあり、人々は例外をキャッチして内部状態を突破してバイトコード操作に突入するということをしました。これは、完全な言語が必要な場合に使用する方法です。
もう1つの方法は、コードを解析し、ast
モジュールを使用して不要な構成(たとえば、インポートステートメント、関数呼び出しなど)をキックアウトし、残りをコンパイルする方法です。これは、Python=を構成言語として使用する場合などに使用する方法です。
別の方法(GAEを使用しているため機能しない場合があります)は PyPyサンドボックス です。私自身は使用していませんが、intertubes上のWordは、サンドボックス化された唯一のrealであるということですPythonそこにあります。
要件の説明に基づいて(要件は変数、基本条件、および関数呼び出し(定義ではない)のサポートです)、あなたmightはアプローチを評価したい2そして、コードから他のすべてを追い出します。少しトリッキーですが、実行可能です。
私の知る限り、完全に分離された環境でコードを実行することが可能です:
exec somePythonCode in {'__builtins__': {}}, {}
しかし、そのような環境ではほとんど何もできません:)(モジュールをimport
することもできません。それでも、悪意のあるユーザーが無限再帰を実行したり、メモリ不足を引き起こす可能性があります。)おそらく、ゲームエンジンへのインターフェイスとなるモジュール。
なぜだれもこれに言及しない理由はわかりませんが、Zope 2にはPython Scriptと呼ばれるものがあります-これはまさに-制限付きPython、ファイルシステムへのアクセスがなく、Zopeセキュリティー機構によって制御されている他のZopeオブジェクトへのアクセスがあり、インポートは安全なサブセットに制限されています。
Zopeは一般にかなり安全なので、サンドボックスから抜け出すための既知の方法や明らかな方法はないと思います。
Pythonスクリプトがどのように実装されているのか正確にはわかりませんが、この機能は2000年の頃からありました。
そして、詳細なドキュメントとともに、PythonScriptsの背後にある魔法があります: http://pypi.python.org/pypi/RestrictedPython -それもそうではないt Zopeに依存しているため、スタンドアロンで使用できます。
これは、任意のpythonコードを安全に実行するためではありません(ほとんどのランダムスクリプトは、最初のインポートまたはファイルアクセス時に失敗します)ではなく、Python Pythonアプリケーション内の制限されたスクリプト用。
この回答は、私のコメントから、この質問の複製としてクローズされた質問への回答です: PythonからのPython:機能の制限?
2つのサーバーによるアプローチを検討します。最初のサーバーは、コードが存在する特権Webサーバーです。 2番目のサーバーは、WebサービスまたはRPCサービスのみを提供し、信頼されていないコードを実行する、非常に厳密に制御されたサーバーです。コンテンツ作成者にカスタムインターフェイスを提供します。たとえば、エンドユーザーがアイテムを作成することを許可した場合、実行するコードとパラメーターのセットを使用してサーバーを呼び出すルックアップがあります。
これが、癒しのポーションの抽象的な例です。
{function_id='healing potion', action='use', target='self', inventory_id='1234'}
応答は次のようになる可能性があります
{hp='+5' action={destroy_inventory_item, inventory_id='1234'}}
うーん。これは思考実験であり、私はそれが行われたことを知りません:
compiler
パッケージを parse
スクリプトに使用できます。次に、このツリーをたどって、すべての識別子(変数、メソッド名など)にプレフィックスを付けます。 (またhas|get|setattr
呼び出しなど)-一意のプリアンブルを使用して、変数を参照できないようにします。また、compiler
パッケージ自体が呼び出されていないこと、およびおそらくファイルを開くなどの他のブラックリストに記載されていることを確認することもできます。次に、pythonこのコードを発行し、 compiler.compile
それです。
ドキュメントは、compiler
パッケージがPython 3.0に含まれていないことを指摘していますが、3.0の代替が何であるかについては触れていません。
一般に、これはフォーラムソフトウェアなどが「安全な」JavascriptまたはHTMLなどをホワイトリストに登録しようとする方法と並行しています。そして、彼らは歴史的にすべての脱出を踏みつけたという悪い記録を持っています。しかし、あなたはPython :)でもっと運があるかもしれません
おそらく、独自のパーサーを作成するためのlibrefの Python言語サービス セクションに興味があるでしょう。
あなたの最善の策は、これまでの回答の組み合わせになると思います。
入力を解析してサニタイズする必要があります。たとえば、インポートステートメントを削除します。
次に、Messaの exec サンプル(または類似のサンプル)を使用して、選択した組み込み変数のみに対してコードを実行できます。おそらく、プログラマーが機能にアクセスできるようにする、自分で定義した何らかのAPIです。あなたは関連があるとみなします。
このwikiページ にいくつかのアイデアがありますが、簡単に実行できるようには見えません。