I tried hack.lu ctf 2020 several easy-web challs. There are write-ups.

FluxCloudFluxCloud Serverless (1.0 and 2.0)

I tried both challenge with same solution. I think I first found solution for 2.0, it also worked to 1.0 version challenge.

It provides node.js server source code.

 

There are a few files in zip file. I carefully audited the code.

In this code, the flag is returned by router.get('/flag');

But it is not that simple, because to reach that app.js code, we should passthrough the serverless/index.js router.

router for /:deploymentId/ handles deploymentRouter and then do waf, after then do app function.

 

But there is interesting concept, that is the billing system.

the app function and waf function is wraped by billed function. billed function is defined in serverless/billing.js

billed function check if the money in account is sufficient to pay the cost for traffic. 

When the demo server created, the virtual account is goes up, with some money. Everytime the billed function is called, the money reduces. I didn't audit that code exactly, maybe the money of deployment server is stored in database implemented by redis. 

The account for waf and for app is different. If I can make deplete only account for WAF, not app, the waf is disabled, then I can access the flag!

 

Taking advantage of try-catch phrase in serverless/index.js /:deploymentId/ router, I tried to trigger exception in waf function.

Auditing waf.js code, it checks multiple encoded url and body with recursive function. With too much call of recursive function call, the stack overflow will be triggered. So, I made a HTTP request a thousands of encoded string like %25252525252525.

If the error in serverside occurs, the response is "rip". I tried that request more times to exhaust ACCOUNT_SECURITY to suppress waf functionality.

Finding response header, X-Billing-Account exists. It means, ACCOUNT_SECURITY deposit is bankrupt.

Let's try to access flag!

Cool.

2.0 version chall could be beated with same solution.

web - Confession

Client send graphql query to server. I googled graphql vulenerabilities.

medium.com/@the.bilal.rizwan/graphql-common-vulnerabilities-how-to-exploit-them-464f9fdce696

 

GraphQL — Common vulnerabilities & how to exploit them

Hello there! how you doin? , Bilal Rizwan here & I hope everyone is safe in this time of crisis and making complete use of your…

medium.com

I tried introspect query to server.

The response tells me something.

I checkd the response carefully.

Then I found there is the schema object named accessLog with properties name, args, timestamp. So I tried graphql for fetch that data.

(id in variable field is random value)

I can get a bunch of accessLogs. There are some hash values.

 

I treid to decyprt sha256 hash from online sha256 decryptor. 

The first one was "f", the second one was "fl", the third is "fla", and fourth is "flag".

There are no more sha256 database to decrypt more hashes.

I wrote simple script to get full flag.

#!/usr/bin/env python3

import string
import hashlib
candid = string.printable
flag = "flag"
hashes = """0577f6995695564dbf3e17ef36bf02ee73ba10ab300caf751315615e0fc6dd37
9271dd87ec1a208d1a6b25f8c4e3b21e36c75c02b62fafc48cf1327bac220e48
95f5e39cb28767940602ce3241def53c42d399ae1daf086c9b3863d50a640a81
62663931ff47a4c77e88916d96cad247f6e2c352a628021a1b60690d88625d75
5534607d1f4ee755bc11d75d082147803841bc3959de77d6159fca79a637ac77
52a88481cc6123cc10f4abb55a0a77bf96d286f457f6d7c3088aaf286c881b76
7ffcb9b3a723070230441d3c7aee14528ca23d46764c78365f5fdf24d0cdef53
532e4cecd0320ccb0a634956598c900170bd5c6f1f22941938180fe719b61d37
a4b24c8f4f14444005c7023e9d2f75199201910af98aaef621dc01cb6e63f1d1
1092c20127f3231234eadf0dd5bee65b5f48ffbdc94e5bf928e3605781a8c0d1
1e261929cc13a0e9ecf66d3e6508c14b79c305fa10768b232088e6c2bfb3efa3
0bb629dfb5bf8a50ef20cfff123756005b32a6e0db1486bd1a05b4a7ddfd16c7
0141c897af69e82bc9fde85a4c99b6e693f6eb390b9abdeda4a34953f82efa4b
c20ee107ba4d41370cc354bb4662f3efb6b7c14e7b652394aaa1ad0341e4a1c9
d6b977c1deb6179c7b9ac11fb2ce231b100cf1891a1102d02d8f7fbea057b8a0
fb7dc9b1be6477cea0e23fdc157ff6b67ce075b70453e55bb22a6542255093f1
70b652dad63cabed8241c43ba5879cc6d509076f778610098a20154eb8ac1b89
26f4fc4aba06942e5e9c5935d78da3512907fe666e1f1f186cf79ac14b82fcad
c31c26dbbcf2e7c21223c9f80822c6b8f413e43a2e95797e8b58763605aaca0d
eb992e46fb842592270cd9d932ba6350841966480c6de55985725bbf714a861d
c21af990b2bd859d99cfd24330c859a4c1ae2f13b0722962ae320a460c5e0468
ebf2b799b6bf20653927092dae99a6b0fc0094abc706ca1dce66c5d154b4542d
07a272d52750c9ab31588402d5fb8954e3e5174fcab9291e835859a5f8f34cf9
5a047cba5d6e0cf62d2618149290180e1476106d71bd9fdb7b1f0c41437c2ff5""".split("\n")

def hash(v):
    return hashlib.sha256(v.encode()).hexdigest()

for hashval in hashes:
    for c in candid:
        if hash(flag + c) == hashval:
            flag += c
            print (flag)
            break
print ("Flag is " + flag)

The flag is flag{but_pls_d0nt_t3ll_any1}

+ Recent posts