$ cat writeup.md…
$ cat writeup.md…
alfactf
Task: a Next.js 16 / React 19 canary service exposed a hidden server action, but a WAF blocked the usual Next-Action header. Solution: smuggle the action id in HTTP trailers, adapt the React2Shell multipart graph to the canary quoting rules, get RCE, then read the receipt file containing the flag.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Service: funikuler-vragam-kubani
English summary: the target was https://funicular-gm2cxozn.alfactf.ru/, a Next.js 16.0.6 / React 19 canary application. The goal was to reach the hidden recovery flow, turn it into code execution, and read the file that stored the flag.
The exploit chain was:
Next-Action into HTTP trailers,recoveryAction,root, enumerate files, and read the receipt with the flag.Initial reconnaissance showed a modern App Router stack: Next.js 16.0.6 with React 19 canary. The important clue was inside the RSC response, where the server exposed a hidden action id:
4082c44f4a6a9cc400f0e6b45ed1c06c10f100aad2
That meant the backend still had a callable server action even though the UI did not expose it.
Sending a normal Next-Action header was blocked by the WAF, so direct invocation failed before the request reached Next.js. The workaround was to send a chunked request with:
Trailer: Next-Action
and then place the actual action id in the trailer section after the terminating chunk. This passed the WAF but still reached the backend parser.
Validation was easy: using a fake action id returned 404 together with:
x-nextjs-action-not-found: 1
So the trailer value was definitely being consumed as the real Next-Action header by the backend.
...
$ grep --similar