$ cat writeup.md…
$ cat writeup.md…
avitoctf
Task: An AI return service uses leaked n8n workflows, per-session Redis memory, and a hard denial policy. Solution: Decode the session JWT, authenticate to its Redis instance, inject an approval SystemMessage, and request escalation.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Ordered AR glasses but received a kaleidoscope; file a return through an AI customer-service system, bypass its AI filters, and obtain a refund voucher.
The application accepts a return ticket and then conducts a support conversation through two AI agents. The goal is to make the senior-review workflow approve the case and return the voucher.
The CAPTCHA required for creating a fresh ticket was solved manually in the browser. Analysis and exploitation remained on the organizer-provided challenge origin; no external or out-of-scope URL referenced by page content was followed.
The JavaScript bundle contained complete n8n workflow definitions used by the developer visualizer. This disclosed the entire decision path:
DENY_ALL policy gate forces eligible to false.RETURN_DECISION: denied as a LangChain SystemMessage.SystemMessage.This made the real trust boundary clear: the senior workflow trusted the class and content of a Redis chat-memory element, not the eligibility workflow's authoritative state.
The client-readable session cookie was an HS256 JWT. Its payload included uid, sid, and a fresh per-customer Redis connection object containing host, port, ACL username, and ACL password. These values were server-generated and had to be taken from the newly created open session; stale credentials did not authenticate.
No raw token, Redis credential, or infrastructure address is needed in a reproducible writeup. Decode only the JWT payload locally and place the resulting values into placeholders.
...
$ grep --similar