skeleton key, cve-2023-27524 simulation
/
—
Challenge 0 : Briefing
You are assessing Celadon Analytics, a web app that reproduces a real 2023 vulnerability class: an application shipped with a default framework signing secret that was never changed before deployment. That single oversight is enough to forge an administrator session with no password. Over the next steps you will uncover it the way an assessor would, from the outside in, using httpx , nuclei , curl and a few other standard tools.
Your Mission:
1. Confirm your toolkit is present: check thatcurl , httpx and nuclei each report a version (for example curl --version ).
2. Make your first request to the target and read the page it returns:curl http://10.11.12.22:5000/
3. Identify the product name shown in the main heading of that page.
Your Mission:
1. Confirm your toolkit is present: check that
2. Make your first request to the target and read the page it returns:
3. Identify the product name shown in the main heading of that page.
Hint:curl prints the raw HTML of a page to your terminal. The product name sits in the main heading near the top of that HTML. Note it: this is the application you will assess for the rest of the room.
Reference: Horizon3.ai: CVE-2023-27524 writeup
CVE severity: Critical (CVSS 8.9)
Affected: Apache Superset < 2.1.0
Challenge 1 : First Probe
Before any deeper work, profile the target's HTTP response. A carelessly configured server will often tell you the exact software and version it runs. That disclosure is a genuine finding in any engagement, because it hands an attacker a shortlist of known vulnerabilities to try.
Your Mission:
1. Usehttpx to probe http://10.11.12.22:5000 in a single command.
2. Make it print the server software and its version that the target reports, along with the status code and the page title.
3. That software-and-version string is your finding: note it down.
Your Mission:
1. Use
2. Make it print the server software and its version that the target reports, along with the status code and the page title.
3. That software-and-version string is your finding: note it down.
Hint: Runhttpx -h and look for the switches that print the status code, the page title, and the server software, plus one to keep the output quiet. Success looks like the application name followed by a version number appearing in your output.
Challenge 2 : Full Fingerprint
A one-line probe is fine for orientation. For documentation you want a fuller fingerprint saved to disk, because a later step reuses it. Extend your previous probe and write the result to a file.
Your Mission:
1. Re-runhttpx against the target, and on top of the status code, title and server software, also capture the content length.
2. Write the output to a file namedceladon_probe.txt instead of to the screen.
3. Read the file back and confirm it holds the target's status line.
Your Mission:
1. Re-run
2. Write the output to a file named
3. Read the file back and confirm it holds the target's status line.
Hint: httpx has a flag for content length and one for writing results straight to a file (the file version strips the colour codes, which is what you want for a report). Keep the fingerprint stable: do not add fields that change on every run, such as response time, or the saved output will never be the same twice. A line showing the target URL with[200] means you are done.
Challenge 3 : Surface Discovery
One URL is not an attack surface. The surface is every endpoint you can reach, and applications often advertise their own sensitive paths in the one file meant to hide them: /robots.txt . Administrators list paths there to keep crawlers away, and in doing so hand you a wordlist.
Your Mission:
1. Read/robots.txt on the target and note every path it lists.
2. Build a file of full URLs to test: the paths from robots.txt, a couple of guesses of your own, and one path you know is fake (as a control).
3. Probe the whole list withhttpx and display the status code for each URL, so you can see which paths are alive and which are not.
Your Mission:
1. Read
2. Build a file of full URLs to test: the paths from robots.txt, a couple of guesses of your own, and one path you know is fake (as a control).
3. Probe the whole list with
Hint: TheDisallow: lines are your wordlist. httpx can read a file of URLs instead of a single target, and the same status-code flag from before makes each result show its[200] ,[404] and so on. One of the live paths is an admin area that should never be reachable without a login.
Challenge 4 : Header Analysis
Live endpoints tell you what exists. The response headers tell you how carefully the app was deployed. A hardened application sets several protective headers; one running on defaults sets almost none. Retrieving and reading those headers is the task here.
Your Mission:
1. Usecurl to fetch only the response headers from the target.
2. Read through them. A production app should carry headers that defend against clickjacking, MIME-type sniffing and more.
3. Note which of those protective headers are absent here: that absence is your finding.
Your Mission:
1. Use
2. Read through them. A production app should carry headers that defend against clickjacking, MIME-type sniffing and more.
3. Note which of those protective headers are absent here: that absence is your finding.
Hint:curl -I http://10.11.12.22:5000 sends a HEAD request and prints just the response headers. Scan the list forX-Frame-Options ,X-Content-Type-Options andContent-Security-Policy . None of them are set here. TheServer line at the top of the same output also re-confirms the software version you found earlier.
Challenge 5 : Nuclei, First Scan
Manual probing orients you; nuclei does the systematic sweep. It ships with thousands of community templates, and pointing all of them at one host is slow and noisy. The skill is to scope the scan to the class of issue you suspect (default configuration and exposed data), run it, and then read the results rather than skim them.
Your Mission:
1. Get a sense of how large the template collection is before you scan anything.
2. Runnuclei against the target, scoped to the template groups relevant to misconfiguration and exposures, at a sensible severity range.
3. Read the findings and pick out the one that hints at exposed configuration or secrets. That finding is your lead into the next challenge.
Your Mission:
1. Get a sense of how large the template collection is before you scan anything.
2. Run
3. Read the findings and pick out the one that hints at exposed configuration or secrets. That finding is your lead into the next challenge.
Hint: nuclei can be scoped by template directory, by tag, and by severity. Explore/opt/nuclei-templates/ to see how the templates are grouped, then decide how you want to narrow the run; there is more than one valid way.nuclei -h shows the relevant flags. Once it prints[INF] Templates loaded , the scan is under way and the findings follow.
Challenge 6 : Finding the Secret Key
This is the core of the vulnerability. One unauthenticated endpoint returns the application's configuration as JSON, including the secret that Flask uses to sign session cookies. Real incidents in this class leaked the same secret through config endpoints, backup files and committed docker-compose files. Read it out.
Your Mission:
1. From the endpoints you mapped, choose the one that returns configuration data.
2. Fetch it withcurl and read the JSON it returns; pipe it through jq so it is laid out cleanly.
3. Find the signing secret in that JSON and keep it: the next challenge depends on it.
Your Mission:
1. From the endpoints you mapped, choose the one that returns configuration data.
2. Fetch it with
3. Find the signing secret in that JSON and keep it: the next challenge depends on it.
Hint: During surface discovery you saw an/api/... path. Usingcurl -s http://10.11.12.22:5000/{the_interesting_path} | jq fetches and pretty-prints it. The field you want is the one Flask signs cookies with.
Challenge 7 : Forging a Session Cookie
This is the CVE payoff. Flask signs the session cookie with the SECRET_KEY , but the contents are only signed, not encrypted, so anyone can read them. With the key you recovered you can also write a valid cookie for any user, including the administrator, with no password at all.
Your Mission:
1. Log in with the analyst account we have prepared for you (analyst / analyst as username and password) and capture the session cookie the server hands back.
2. Read that cookie's contents. This needs no key at all: the cookie is signed, not encrypted, so its fields are public.
3. You are user id 2, an analyst. Using theSECRET_KEY from the previous challenge, forge a cookie that makes you user id 1, the administrator.
4. Present the forged cookie to/admin and confirm you reach the Admin Panel.
Your Mission:
1. Log in with the analyst account we have prepared for you (
2. Read that cookie's contents. This needs no key at all: the cookie is signed, not encrypted, so its fields are public.
3. You are user id 2, an analyst. Using the
4. Present the forged cookie to
Hint:flask-unsign --decode --cookie '<cookie>' prints the payload with no secret at all, which is exactly why a signed-but-not-encrypted cookie is so dangerous once the key leaks. Re-signing is the step that needs the key:flask-unsign --sign --secret '<recovered key>' --cookie '<the same fields, id set to 1>' . Send the result withcurl -b "session=<forged>" . Logging in only ever gives you an analyst cookie; the leaked key is what turns it into an admin one without the admin's password.
Challenge 8 : Writing a Detection Template
Replicating the attack is half the job; detecting it at scale is the other half. That is what turned this bug from one finding into thousands: an automated check anyone could run. You will write a nuclei template that flags this misconfiguration by requesting the config endpoint and matching a response that exposes a known weak secret.
Your Mission:
1. Write a template fileceladon-default-secret-key.yaml . Give it the id celadon-default-secret-key and a sensible info block (name, author, severity that must be high, description, a reference to CVE-2023-27524).
2. In thehttp section, send a GET to the config endpoint you already found.
3. Add matchers so the template fires only on a real hit: the status must be 200 and the body must contain the tell-tale secret indicators.
4. Run your template against the target and confirm it fires.
Your Mission:
1. Write a template file
2. In the
3. Add matchers so the template fires only on a real hit: the status must be 200 and the body must contain the tell-tale secret indicators.
4. Run your template against the target and confirm it fires.
Hint: A nuclei template is YAML in three parts: anid , aninfo block, and a protocol block (herehttp ). Undermatchers you can combine astatus matcher and aword matcher, andmatchers-condition: and requires both, which stops a 404 page from triggering a false positive. The examples under/opt/nuclei-templates/ are the fastest way to learn the exact syntax: find one that is close and adapt it. Run it withnuclei -u http://10.11.12.22:5000 -t celadon-default-secret-key.yaml .
The best resource if you need help writing the template : Nuclei's Template Structure Documentation.
If nuclei does not recognize your template, use-debug to see why!