5 min read

CA CTF 2022: Exploiting LFR and forging Cookies - Mutation Lab

Exploiting LFR and forging Cookies, Rayhan0x01 shares his write-up of Mutation Lab from Cyber Apocalypse CTF 2022.

Rayhan0x01 avatar

May 15

In this write-up, we'll go over the web challenge Mutation Lab, rated as medium difficulty in the Cyber Apocalypse CTF 2022. The solution requires exploiting a local file read vulnerability to steal the cookie signing key and crafting a session cookie for the admin.

Challenge Description 📄

One of the renowned scientists in the research of cell mutation, Dr. Rick, was a close ally of Draeger. The by-products of his research, the mutant army wrecked a lot of havoc during the energy-crisis war. To exterminate the leftover mutants that now roam over the abandoned areas on the planet Vinyr, we need to acquire the cell structures produced in Dr. Rick's mutation lab. Ulysses managed to find a remote portal with minimal access to Dr. Rick's virtual lab. Can you help him uncover the experimentations of the wicked scientist?

The application at-a-glance 🔍

The application homepage displays a login form and a link to the registration page. Since we don't have an account, we can create an account via the registration page and log in. After logging in, the application redirects to the following dashboard page:

We can interact with the two canvas elements displayed on the webpage. Clicking on the buttons below the canvas exports a PNG image file of the canvas. Clicking the export button sends the following API request to the server:

That is pretty much all the accessible features in this web application.

The LFR vulnerability that lets you see the unseen 🔭

Clicking the second export button downloads a PNG image of the second canvas but the Networks tab in the browser shows two different requests that originated when we click the button:

Looking into the client-side JavaScript code of the dashboard.js file, the button with the id exportTadpoleCanvas has two onClick event handlers specified to call the exportExp function:

$('#exportCellCanvas').on('click', () => {exportExp(scope1)});
$('#exportTadpoleCanvas').on('click', () => {exportExp(scope2)});
$('#exportTadpoleCanvas').on('click', () => {exportExp(scope3)});
const exportExp = async (scope) => {
await fetch(`/api/export`, {
   method: 'POST',
   headers: {
     'Content-Type': 'application/json',
   body: JSON.stringify({
     svg: scope.project && scope.project.exportSVG({asString: true})
 .then((response) => response.json())
   .then((data) => {
     if (data.hasOwnProperty('png')) {
 .catch((error) => {

The scope3.project attribute is null, which causes the second request to fail as the request JSON parameter svg is null. The response contains an error stack trace:

From the error stack trace, we can see the convert-svg-core npm module is used to convert the SVG code to a PNG image. Searching for vulnerabilities in this module leads us to the following Snyk advisory page:


The advisory contains a proof-of-concept payload that we can send to the API to read the server-side file /app/index.js:

 "svg":"<svg-dummy></svg-dummy>\n<iframe src=\"///app/index.js\" width=\"100%\" height=\"1000px\"></iframe><svg viewBox=\"0 0 240 80\" height=\"1000\" width=\"1000\" xmlns=\"http://www.w3.org/2000/svg\"> <text x=\"0\" y=\"0\" class=\"Rrrrr\" id=\"demo\">data</text></svg>"

Sending the above payload to the /api/export endpoint returns a PNG image URL which discloses the application source code in the exported PNG image file: