[CSSCTF] Web Exploitation Challenges Writeup#
Author: k0z1l
Category: Web Exploitation
Flag Format: CSSCTF{...}
1. Secret Supernovas#
Flag:
CSSCTF{we_l000ve_grafs}
Difficulty: Medium
Target:http://34.116.80.78:9982/
Category: Web / GraphQL API Security
Vulnerability: Broken Object Property Level Authorization (BOPLA / OWASP API3:2023)
1.1. TL;DR & Exploitation Summary#
| |
1.2. Challenge Description & Overview#
This is just a list of stars. Nothing else to see here…
The challenge statement is intentionally understated. In reality, the application serves an astronomical star catalogue backed by an inadequately secured GraphQL API that conceals confidential data.
1.3. Reconnaissance#
1.3.1. Inspecting the Landing Page#
Navigating to http://34.116.80.78:9982/ displays the login interface:
| |
The login form explicitly reveals default visitor credentials: cadet/star.
Initial observations:
- Application name: Star City Observatory
- Framework: SvelteKit (identified via Svelte SVG logos and compiled client asset structure)
- Form-based authentication with potential role segregation
1.4. Authentication and Session Analysis#
1.4.1. Authenticating as cadet/star#
| |
Result: The endpoint responds with JSON redirect instructions rather than an HTTP 303 status code, typical of SvelteKit form actions. A session cookie is established with HttpOnly; SameSite=Lax.
1.4.2. Accessing the Authenticated Dashboard#
| |
The returned HTML includes embedded session details in the client-side bootstrap state:
| |
The user cadet has id = 10 and name “Cadet Visitor”, representing an unprivileged guest profile.
The page initially displays "Aligning telescope…", showing that star records are retrieved asynchronously via client-side JavaScript rather than rendered server-side. This points to a dedicated backend API endpoint.
1.5. JavaScript Bundle Analysis#
1.5.1. Inspecting Application Bundles#
The SvelteKit entry point enumerates route chunks:
| |
Route mapping:
| |
1.5.2. Analyzing Node 2 - The Stars Component#
Downloading /_app/immutable/nodes/2.C521ycad.js reveals the data retrieval logic:
| |
Key Finding: The client sends queries to a GraphQL endpoint at /graphql. The query specifies only a partial set of fields (id name spectralClass magnitude classification galaxy), leaving open the possibility of unexposed schema fields.
1.6. GraphQL Exploitation & Flag Capture#
1.6.1. Schema Introspection#
GraphQL features an introspection system allowing clients to query schema definitions. With introspection enabled on the target, the complete schema structure can be recovered:
| |
Extracted Schema:
| |
Identified Flaw: Type Star contains an owner field returning a Person object that is not queried by the frontend. The Person.description field may hold sensitive data. This constitutes Broken Object Property Level Authorization (BOPLA).
1.6.2. Querying the Hidden owner.description Field#
Constructing a query requesting the hidden owner properties:
| |
1.6.3. Flag Extraction & Verification#
Extract from the GraphQL response:
| |
Star entry #11 is named “Secret Supernova”, referencing the challenge title. It is owned by Oliver Queen (Observatory Director), while the flag is embedded within the description of Laurel Lance, owner of “Black Canary”.
Captured Flag:
CSSCTF{we_l000ve_grafs}
1.7. Attack Flowchart#
| |
1.8. Vulnerability Analysis & Remediation#
1.8.1. Vulnerability Classification: BOPLA and Schema Exposure#
OWASP API3:2023 — Broken Object Property Level Authorization
| Metric | Details |
|---|---|
| Vector | GraphQL field owner.description lacks property-level access enforcement |
| Prerequisites | Low-privilege authenticated session (cadet visitor account) |
| Exposed Data | Sensitive attributes within the Person type (description) |
| Root Cause | Frontend requests only a safe subset of properties, but backend schema does not validate field-level permissions |
1.8.2. Root Causes#
- Client-side filtering assumption: The UI only queries
stars { id name spectralClass magnitude classification galaxy { name } }, omittingowner. - Missing field-level authorization: Authenticated users can request
owner { description }without restriction. - Active GraphQL Introspection: Introspection enabled in production allows attackers to enumerate the complete data schema.
1.8.3. Remediation#
| |
1.9. Complete Exploit Script#
| |
Execution Output:
| |
1.10. Key Takeaways#
- Never rely on frontend filtering for sensitive data isolation: Any data exposed by GraphQL types can be queried regardless of whether UI views render it.
- Disable GraphQL introspection in production: Open introspection reveals the schema architecture and assists attackers in locating unexposed fields.
- Implement property-level authorization: Secure individual schema fields and nested types, not merely top-level operations.
- Eliminate exposed credentials from client code and markup: Even low-privilege demo accounts provide an initial foothold for authorized API exploration.
- Analyze client JavaScript bundles during assessments: Single-page application bundles often disclose unpublished API paths and operational logic.
