This is the challenge for WMCTF 2024 in the category of Web.
The challenge is presented as black-box, source code not provided. Only the first 10 lines of index.ts are presented.
Years ago, an OI contestant submitted the code which stole the answer file from the judge machine and output them. Evidently, WA, out! What if we delete those files after reading? Now even in CTF, it's also hard to get AC.
Because the bun runtime requires HTTP requests with support for io_uring's connect() operation, The docker instance should be deployed on a Linux machine with a kernel version of at least 5.6. You can refer to bun install - For Linux users.
The give lines shows the program read the content of flag.txt and then delete it. On linux, however, the file descriptor is not actually closed until the program exits. So we can reach it by proc file system, known as /proc/<PID>/fd/<FD>.
The server will use Deno to run user's uploaded script(s). Though Deno prevent IO, Socket, and other dangerous operations by default, the import statement can still be used to load module from local or remote.
Take a consider of the following code:
import './flag.ts';If flag.ts is not a valid TypeScript module, Deno will throw an error, which contains the line where the error occurred. This could be used to leak the content of flag.ts.
However, importing non-js or non-ts file will be rejected, and asynchronous importing will hit the permission guard.
To rename the file descriptor, we're going to upload a ZIP file with a symlink (flag.ts -> /proc/<PID>/fd/<FD>), and an entry file which imports flag.ts. Therefore, the server is expected to extract (unzip) it and import the file descriptor. Just visit /status route to get the PID number of bun server, as it's given by /robots.txt.
The exploit script is available at exploit/exp.js. Please execute via bun run exp.js after JSZip dependency is installed.
CopyRight (c) Cnily03. All rights reserved.
Licensed under the MIT License.