Eu sei que é desaconselhável usar eval()
em entradas não confiáveis, mas eu quero ver onde esse sanitizador falha. Ele usa uma lista de permissões para permitir apenas builtins inofensivos, e ele imediatamente desiste se houver alguma propriedade dunder chamada. (Nota: a razão pela qual ele faz buscas de string .__
e não apenas __
é porque eu quero permitir coisas como foo.bar__baz
).
def safe_eval(code: str) -> Any | None:
if '.__' in code:
raise ValueError
allowed_builtins = [
'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr',
'complex', 'dict', 'divmod', 'enumerate', 'filter', 'float', 'format', 'frozenset',
'hasattr', 'hash', 'hex', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'list',
'map', 'max', 'min', 'next', 'object', 'oct', 'ord', 'pow', 'range', 'repr', 'reversed',
'round', 'set', 'slice', 'sorted', 'str', 'sum', 'tuple', 'zip'
]
return eval(
code,
globals={
'__builtins__': {
builtin : getattr(__builtins__, builtin) for builtin in allowed_builtins
}
},
locals={},
)
Re: "Por que você quer fazer isso?" Eu quero poder filtrar objetos python com base na entrada do usuário. Esses objetos são "payloads" para "sessões" no aplicativo, então permitir que os usuários filtrem sessões com base em expressões arbitrárias em conteúdos de payload - por exemplo len(payload.things) > 12
- seria um recurso útil.
Então minha pergunta é: qual string de entrada permitiria que um invasor acessasse dados "fora" da avaliação, ou seja, variáveis no script ou acesso ao sistema operacional?