MusicBlog — zer0pts CTF 2020
You can introduce favorite songs to friends with MusicBlog
!
Challenge (URL)
题目文件: MusicBlog_637545797ab8638bffd877d7be2ec045.tar.gz
是一个Blog。在发布文章时可以选择是否公开,如果设置为公开,admin用户会自动访问该文章并点赞。写文章时可以使用 [[URL]]
语法,将其插入到句子中会展开成
这样的audio元素。
首先,确认flag在哪。搜索 zer0pts{
,能够发现flag在 worker/worker.js
中,这是admin自动访问代码的一部分。
// (snipped) const flag = 'zer0pts{}'; // (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)
await page.setUserAgent(flag);
,会将User-Agent设置为flag。那么首先,考虑找到一个使用 [[URL]]
进行外部请求的方法,但是 Content-Security-Policy: default-src 'self'; object-src 'none'; script-src 'nonce-yuAhic5Y6HSsT0e5zC8Qlg==' 'strict-dynamic'; base-uri 'none'; trusted-types
,严格的CSP策略会禁止这样。
但是,admin会进行 await page.click('#like');
,如果能够将一个可控元素的id设置为like,就可以利用admin的click,考虑通过XSS将admin重定向访问到外部。
查看文章的单独页面post.php, 能够发现这里将文章内容作为参数,经过 render_tags
后返回值显示在页面上。
︙= render_tags($post['content']) ?>︙
render_tags
在 utils.php
中定义:
function render_tags($str) { $str = preg_replace('/\[\[(.+?)\]\]/', '', $str); $str = strip_tags($str, '
[[URL]]
替换为
之后,通过 strip_tags
将 audio
之外的标签消除来防止XSS。那如果使用 [[">]]
作为URL,经过这种处理之后就变成了
,
和
都被删除了,做不了什么。
看一下Web server的Dockerfile,可以看到使用的是PHP 7.4.0, 截至2020年3月7日,最新版本为PHP 7.4.3,看起来稍微有点老,因此可以看一下PHP 7.4.0之后的 PHP 7.4.1的ChangeLog
。
- Fixed bug #78814 (strip_tags allows / in tag name => whitelist bypass).
可以看到修复了 strip_tags
的一个bug,详细说明见 https://bugs.php.net/bug.php?id=78814
Bug #78814 strip_tags allows / in tag name, allowing whitelist bypass in browsers
When strip_tags is used with a whitelist of tags, php allows slashes (“/”) that occur inside the name of a whitelisted tag and copies them to the result.
For example, if is whitelisted, then a tag
is also kept.
Test script: --------------- b", ""); Expected result: ---------------- b Actual result: --------------b
将
作为白名单时,添加斜杠的
没有被删除,原样输出。MusicBlog 中使用的是
作为白名单,
可以通过函数处理,并且
会作为 超链接
被解析。
这样admin自动去点击id为like的标签的话,会点击到我们可控的外部链接。
$ nc -lvp 8000 Listening on [0.0.0.0] (family 0, port 8000) Connection from ec2-3-112-201-75.ap-northeast-1.compute.amazonaws.com 33926 received! GET / HTTP/1.1 ︙ Connection: keep-alive Upgrade-Insecure-Requests: 1 User-Agent: zer0pts{M4sh1m4fr3sh!!} Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 ︙ Accept-Encoding: gzip, deflate Accept-Language: en-US