2021祥云杯-secrets_of_admin


2021祥云杯-secrets_of_admin

知识点概要:审计、XSS+SSRF组合拳

首页

有源码,源码结构:

database.ts文件里有admin账户密码,可以直接登录。另外可以看出有users和files两个表,还有一个superuser用户

登录之后进入/admin目录,在文本框随便输入,会提示,大致意思是保存成了pdf文件,但是需要知道怎么下载

源码分析

审计index.ts,几个关键路由

根目录,做登录验证,登录成功设置cookie,并重定向到/admin目录

/admin目录

1.POST提交content参数值,会有几个类似XSS的黑名单过滤;

2.将content直接拼接到一段HTML代码标签里;

3.将HTML代码写入pdf文件,pdf以uuid()的值命名,存在./files/路径下;

4.用文件名计算checksum值,将superuser、文件名、checksum值一块存入数据库。

/api/files目录

1.正则匹配请求地址的socket(IP:PORT),要求冒号前(即IP地址)只能是127.0.0.1;

2.GET参数:username、filename、checksum只能是字符串类型,会被存储到数据库

/api/files/:id目录

1.token的username不能是superuser;

2.token的username和请求参数id会被用来查找数据库文件名;

3.全场唯一读文件函数readFile读取../files/路径下的对应文件。

数据库getFile()操作代码如下,可以看到传入的参数id对应checksum,从files表中查找对应的文件名

捋一下思路

1.读文件需要token的username是admin,并且知道文件对应的checksum值;

2.要保证token的username是admin,只需正常登录admin账户就可以;

3.文件对应的checksum值则有两条路线,一条是/admin路由的uuid()生成的文件名计算所得,这不可控,另一条是通过/api/files路由的GET参数传入。并且从最初的database.ts可以看到,flag文件属于superuser用户,所以这里也需要通过/api/files路由传入一条username=admin&filename=flag的数据,那么checksum就可以随意设置;

4.又因为/api/files路由只能通过127.0.0.1访问,所以必须通过/admin路由的XSS来构造SSRF请求;

5./admin路由的XSS过滤只是对content参数过滤,所以只需以content数组的形式传入即可绕过。

综上,目标:以admin登录,/admin路由POST传入payload,/api/files/:id访问

Payload如下

content[]=<img+src%3D"http%3A//127.0.0.1:8888/api/files?username%3Dadmin%26filename%3D./flag%26checksum%3D999">
或
content[]=%3Cscript%3E%0Avar%20xhr%20%3D%20new%20XMLHttpRequest()%3Bxhr.open(%22GET%22%2C%20%22http%3A%2F%2F127.0.0.1%3A8888%2Fapi%2Ffiles%3Fusername%3Dadmin%26filename%3D.%2Fflag%26checksum%3D999%22%2C%20true)%3Bxhr.send()%3B%0A%3C%2Fscript%3E

再访问/api/files/999,就会把文件下载下来,打开即可看到flag

注:这里端口用8888是因为app.ts文件中设置路由监听端口是8888

参考

https://err0r.top/article/2021xyb/

https://blog.csdn.net/cjdgg/article/details/120238587


文章作者: wa0er
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 wa0er !
评论
  目录