IT

python의 eval () 대 ast.literal_eval ()을 사용합니까?

lottoking 2020. 6. 12. 08:35
반응형

python의 eval () 대 ast.literal_eval ()을 사용합니까?


eval()가능한 해결책으로 나온 코드가있는 상황이 있습니다. 이제는 eval()전에 사용해 본 적이 없지만 잠재적 위험에 대한 많은 정보를 접하게되었습니다. 즉, 나는 그것을 사용하는 것에 대해 매우 조심합니다.

내 상황은 사용자가 입력 한 것입니다.

datamap = raw_input('Provide some data here: ')

datamap사전이 필요한 . 나는 주변을 둘러 보았고 이것이 eval()해결할 수 있다는 것을 알았 습니다. 데이터를 사용하기 전에 입력 유형을 확인할 수 있다고 생각했는데 이는 가능한 보안 예방 조치입니다.

datamap = eval(raw_input('Provide some data here: ')
if not isinstance(datamap, dict):
    return

나는 문서를 읽었으며 이것이 안전한지 확실하지 않습니다. eval은 데이터를 입력하자마자 또는 datamap변수가 호출 된 후 데이터를 평가합니까 ?

는 IS ast모듈의 .literal_eval()유일한 안전 옵션은?


datamap = eval(raw_input('Provide some data here: '))안전하지 않은 것으로 판단 하기 전에 실제로 코드 평가한다는 의미입니다 . 함수가 호출 되 자마자 코드를 평가합니다. 의 위험도eval 참조하십시오 .

ast.literal_eval 입력이 유효한 Python 데이터 유형이 아닌 경우 예외를 발생 시키므로 코드가 입력되지 않으면 실행되지 않습니다.

ast.literal_eval필요할 때마다 사용하십시오 eval. 일반적으로 리터럴 파이썬 문장을 평가해서는 안됩니다.


ast.literal_eval() Python 구문의 작은 하위 집합 만 유효하다고 간주합니다.

제공된 문자열 또는 노드는 문자열, 숫자, 튜플, 목록, dicts, 부울 및 없음과 같은 Python 리터럴 구조로만 구성 될 수 있습니다.

전달 __import__('os').system('rm -rf /a-path-you-really-care-about')로하는 것은 ast.literal_eval()오류를 제기하지만, eval()즐겁게 드라이브를 닦아 주실 것이다.

사용자가 일반 사전 만 입력하게하는 것처럼 보이기 때문에을 사용하십시오 ast.literal_eval(). 그것은 당신이 원하는 것을 안전하게하고 더 이상 아무것도하지 않습니다.


eval : 이것은 매우 강력하지만 신뢰할 수없는 입력에서 평가하기 위해 문자열을 수락하면 매우 위험합니다. 평가되는 문자열이 "os.system ( 'rm -rf /')"이라고 가정하십시오. 실제로 컴퓨터의 모든 파일을 삭제하기 시작합니다.

ast.literal_eval : 파이썬 리터럴 또는 컨테이너 디스플레이를 포함하는 표현식 노드 또는 문자열을 안전하게 평가합니다. 제공된 문자열 또는 노드는 문자열, 바이트, 숫자, 튜플, 목록, dicts, 세트, ​​부울, 없음, 바이트 및 세트와 같은 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]객체 자체는 없습니다. 이제 모든 하위 클래스를 인스턴스화 했습니다. 여기서 주요 enter code here목표는 n 이라는 하나의 클래스를 찾는 것입니다.

We need to code object and function object from instantiated subclasses. This is an alternative way from CPython to access subclasses of object and attach the system.

From python 3.7 ast.literal_eval() is now stricter. Addition and subtraction of arbitrary numbers are no longer allowed. link


Python's eager in its evaluation, so eval(raw_input(...)) will evaluate the user's input as soon as it hits the eval, regardless of what you do with the data afterwards. Therefore, this is not safe, especially when you eval user input.

Use ast.literal_eval.


As an example, entering this at the prompt will be very, very bad for you:

__import__('os').system('rm -rf /a-path-you-really-care-about')

If all you need is a user provided dictionary, possible better solution is json.loads. The main limitation is that json dicts requires string keys. Also you can only provide literal data, but that is also the case for literal_eval.


I was stuck with ast.literal_eval(). I was trying it in IntelliJ IDEA debugger, and it kept returning None on debugger output.

But later when I assigned its output to a variable and printed it in code. It worked fine. Sharing code example:

import ast
sample_string = '[{"id":"XYZ_GTTC_TYR", "name":"Suction"}]'
output_value = ast.literal_eval(sample_string)
print(output_value)

Its python version 3.6.

참고URL : https://stackoverflow.com/questions/15197673/using-pythons-eval-vs-ast-literal-eval

반응형