Webmedium
Incident(al) Report
by Pavel Knespl (capyplivl)
A Flask status-page app serves GET /api/incidents, which mixes public and [INTERNAL] incidents. The filter defaults to returning everything when the public query parameter is omitted, so internal incidents (including one carrying the flag) leak.
Solve
- Inspect
app.py. The list contains public and internal incidents, and one internal incident (#219 "[INTERNAL] Retro: customer-data anomaly") embeds the flag in a "Postmortem" update body viaflag = os.environ.get("FLAG", ...). - Read the filter logic:
The front-end only ever callsv = request.args.get("public") if v is None: selected = data elif v.lower() in {"1","true","yes"}: selected = [i for i in data if i["public"]] elif v.lower() in {"0","false","no"}: selected = [i for i in data if not i["public"]] else: selected = [i for i in data if i["public"]]?public=1. Omittingpublicreturns every incident;public=0returns only the internal ones. - Start the instance, then GET
/api/incidents(or/api/incidents?public=0) and grep the response for the flag:
The flag is in incident #219's "Postmortem" update body.curl -s 'https://<target>/api/incidents' | grep -oE 'SVIBGR\{[^}]*\}'
Flag: SVIBGR{pr073c7_y0ur_s747us_p4g3s}