6

わかった。私専門家話したのを知っ ています、そしてあなたは決して信頼できないデータにPythonを使うべきではありません。私は他の世界より頭が良くないので、これを試してはいけません。だが!とにかく行きます。 eval()

私の基本的な問題は、Pythonの構文のサブセットを使用して、信頼できない入力を受け取る小さな計算機評価プログラムを作成しようとしていることです。私は知っています:plyまたはpyparsingを使用して、パーサーを作成します。グローバル変数とローカル変数を渡すことで失敗してeval()も、うまくいきません。

私が見た(そして心配していた)すべてのアプローチは、悪を列挙しようとします。ここでは、適切なものを列挙しようとしています。ASTを取得し、いくつかのノードタイプのみを許可してから、ホワイトリストに登録された関数のセットの1つに対する呼び出しであることを確認します。これがミニ実装(および要点)です:

import ast
import math

SAFE_FX = {
    'exp': math.exp,
}

SAFE_NODES = set(
    (ast.Expression,
    ast.Num,
    ast.Call,
    ast.Name,
    ast.Load,
    ast.BinOp,
    ast.Add,
    ast.Sub,
    ast.Mult,
    ast.Div,)
)

class CleansingNodeVisitor(ast.NodeVisitor):
    def generic_visit(self, node):
        if type(node) not in SAFE_NODES:
            raise Exception("%s not in SAFE_NODES" % type(node))
        super(CleansingNodeVisitor, self).generic_visit(node)

    def visit_Call(self, call):
        if call.func.id not in SAFE_FX:
            raise Exception("Unknown function: %s" % call.func.id)

def my_safe_eval(s):
    tree = ast.parse(s, mode='eval')
    cnv = CleansingNodeVisitor()
    cnv.visit(tree)
    compiled = compile(tree, s, "eval")
    return(eval(compiled, SAFE_FX))

だから、トリックしmy_safe_eval('2*(4+exp(1.3))')ながらも機能し、同様に禁止されています-禁止などなしで。my_safe_eval('[].__class__')my_safe_eval('open("/something/evil")')__builtins____locals__

私は...これはうまくいくと思います。私は怒っていますか?

4

2 に答える 2

3

Zope にはRestrictedPythonと呼ばれるものがあります。少なくともアプローチを検証したり、コードを再利用したりするために、それを確認することをお勧めします。構成可能で再利用可能です。

これは、同様の質問に対する私の他の回答です。

于 2012-09-21T02:55:07.160 に答える
2

astevalを試してみてください。必要なもののようです。それ以外の場合は、この安全な評価があります

于 2013-01-25T10:04:19.363 に答える