[python] 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 이라는 하나의 클래스를 찾는 것입니다.
인스턴스화 된 서브 클래스에서 이의를 제기 code
하고 function
이의를 제기 해야합니다 . 이것은 CPython
객체의 서브 클래스에 액세스하고 시스템을 연결 하는 대체 방법입니다 .
파이썬 3.7부터 ast.literal_eval ()이 더 엄격 해졌습니다. 더 이상 임의의 숫자를 더하거나 뺄 수 없습니다.링크
답변
파이썬 은 평가에 열중 하므로 나중에 데이터로 무엇을 하든지 상관없이 eval(raw_input(...))
사용자 입력이에 도달하자마자 평가합니다 eval
. 따라서, 이것은 특히 eval
사용자가 입력 할 때 안전하지 않습니다 .
사용하십시오 ast.literal_eval
.
예를 들어, 프롬프트에서 이것을 입력하면 매우 나쁘게됩니다.
__import__('os').system('rm -rf /a-path-you-really-care-about')
답변
사용자가 제공 한 사전 만 있으면 더 나은 해결책이 json.loads
있습니다. 주요 제한 사항은 json dicts에 문자열 키가 필요하다는 것입니다. 또한 리터럴 데이터 만 제공 할 수 있지만이 경우도 마찬가지입니다 literal_eval
.
답변
나는 붙어 있었다 ast.literal_eval()
. IntelliJ IDEA 디버거에서 시도했지만 계속 반환되었습니다.None
디버거 출력으로 .
그러나 나중에 출력에 변수를 할당하고 코드로 인쇄했습니다. 잘 작동했습니다. 공유 코드 예 :
import ast
sample_string = '[{"id":"XYZ_GTTC_TYR", "name":"Suction"}]'
output_value = ast.literal_eval(sample_string)
print(output_value)
파이썬 버전 3.6.