eval:
これは非常に強力ですが、信頼できない入力から評価する文字列を受け入れると非常に危険です。評価される文字列が「os.system('rm -rf /')」であるとしますか? コンピューター上のすべてのファイルの削除が実際に開始されます。
ast.literal_eval:
Python リテラルまたはコンテナー表示を含む式ノードまたは文字列を安全に評価します。提供される文字列またはノードは、次の Python リテラル構造のみで構成されている場合があります: 文字列、バイト、数値、タプル、リスト、辞書、セット、ブール値、なし、バイト、およびセット。
構文:
eval(expression, globals=None, locals=None)
import ast
ast.literal_eval(node_or_string)
例:
# python 2.x - doesn't accept operators in string format
import ast
ast.literal_eval('[1, 2, 3]') # output: [1, 2, 3]
ast.literal_eval('1+1') # output: ValueError: malformed string
# python 3.0 -3.6
import ast
ast.literal_eval("1+1") # output : 2
ast.literal_eval("{'a': 2, 'b': 3, 3:'xyz'}") # output : {'a': 2, 'b': 3, 3:'xyz'}
# type dictionary
ast.literal_eval("",{}) # output : Syntax Error required only one parameter
ast.literal_eval("__import__('os').system('rm -rf /')") # output : error
eval("__import__('os').system('rm -rf /')")
# output : start deleting all the files on your computer.
# restricting using global and local variables
eval("__import__('os').system('rm -rf /')",{'__builtins__':{}},{})
# output : Error due to blocked imports by passing '__builtins__':{} in global
# But still eval is not safe. we can access and break the code as given below
s = """
(lambda fc=(
lambda n: [
c for c in
().__class__.__bases__[0].__subclasses__()
if c.__name__ == n
][0]
):
fc("function")(
fc("code")(
0,0,0,0,"KABOOM",(),(),(),"","",0,""
),{}
)()
)()
"""
eval(s, {'__builtins__':{}})
上記のコードでは().__class__.__bases__[0]
、オブジェクト自体だけです。ここで、すべてのサブクラスをインスタンス化しました。ここでの主な目的は、そこからnenter code here
という名前のクラスを 1 つ見つけることです。
インスタンス化されたサブクラスからcode
オブジェクトとオブジェクトを作成する必要があります。function
これは、CPython
オブジェクトのサブクラスにアクセスしてシステムをアタッチする別の方法です。
Python 3.7 から ast.literal_eval() はより厳密になりました。任意の数値の加算と減算は許可されなくなりました。リンク