Critical Vulnerability Patched in GiveWP Plugin

Published 10 January 2025
Updated 23 January 2025
Table of Contents

GiveWP

Unauthenticated PHP Object Injection

100k
CVSS 9.8

The vulnerability in the GiveWP plugin was originally reported by Patchstack Alliance community member Edisc from Zalopay Security to the Patchstack Zero Day bug bounty program for WordPress.

Patchstack Zero Day program has awarded the researcher a bounty of $2,600 USD. If you wish to participate in the program, you can join the community here. An additional monthly bounty based on the leaderboard has been awarded to the researcher outside the zero-day bounty.

This blog post is about the GiveWP plugin vulnerability. If you’re a GiveWP user, please update the plugin to at least version 3.19.4.

If you are a Patchstack customer, you are protected from this vulnerability already, and no further action is required from you.

For plugin developers, we have security audit services and Enterprise API for hosting companies.

About the GiveWP Plugin

The plugin GiveWP which has over 100,000 active installations, is one of the most widely used donation and fundraising plugins in the WordPress ecosystem. This plugin is developed by GiveWP.

According to their official WordPress plugin page, “GiveWP is the highest rated, most downloaded, and best supported donation plugin for WordPress. Whether you need a simple donate button or a powerful donation platform optimized for online giving, GiveWP is right for you.”

The security vulnerability

The plugin (version 3.19.3 and below) suffers from an unauthenticated PHP Object Injection vulnerability. The vulnerability occurred due to the insecure storage of meta in the DB which ended up being unserialized. This issue has been previously found and fixed by GiveWP in version 3.14.2 and prior. Patchstack Alliance member Edisc From Zalopay Security was able to find a bypass to the fix leading to yet another unauthenticated PHP object injection tracked as CVE-2025-22777.

The previous vulnerability CVE-2024-5932 was in the give-form-title and give_title parameters which was not validated before being saved. The vendor patched the issue by adding those field checks for serialized content. However, the whole serialized check was bypassable due to a weak regex check of the strings. An attacker could enter gibberish text in between the serialized payload that would make the regex check ineffective and store the malicious metadata in the DB that would eventually be deserialized.

The underlying function containsSerializedDataRegex() had the below check in place and could be bypassed:

public static function containsSerializedDataRegex($data): bool
{
    if ( ! is_string($data)) {
        return false;
    }

    $pattern = '/
    (a:\d+:\{.*\}) |         # Matches arrays (e.g: a:2:{i:0;s:5:"hello";i:1;i:42;})
    (O:\d+:"[^"]+":\{.*\}) | # Matches objects (e.g: O:8:"stdClass":1:{s:4:"name";s:5:"James";})
    (s:\d+:"[^"]*";) |       # Matches strings (e.g: s:5:"hello";)
    (i:\d+;) |               # Matches integers (e.g: i:42;)
    (b:[01];) |              # Matches booleans (e.g: b:1; or b:0;)
    (d:\d+(\.\d+)?;) |       # Matches floats (e.g: d:3.14;)
    (N;)                     # Matches NULL (e.g: N;)
    /x';

    return preg_match($pattern, $data) === 1;
}

The exploit scenarios are similar to the previous finding which involves donation form submission. While the last vulnerability relied on injecting the malicious payload in the unchecked parameters, this one is a bypass of the protection. Except the ones that have a custom validation like amount, currency and email, all the parameters are vulnerable to the object injection since the check which relies on protecting from the serialized object is being bypassed. The function give_clean plays a role in bypassing the regex.

function give_clean($var, $allow_serialized_data = false)
{
    if (is_array($var)) {
        return array_map('give_clean', $var);
    }

    if ( Utils::isSerialized($var)) {
        $var = $allow_serialized_data ? Utils::safeUnserialize($var) : '';
    }

    return is_scalar($var) ? sanitize_text_field(wp_unslash($var)) : $var;
}

The researcher was able to bypass the previous check using a special character sequence such as “%25F0%259F%2598%25BC” which converts to 😼. Note that the serialization check is being done before the sanitization which is the root cause of the bypass. The payload with the cat emoji gets sent for regex serialization check, which gives false and proceeds with the request. However, soon afterwards, the payload is passed to the sanitize_text_field function which strips all the emojis and makes it a valid serialized payload which ends up getting deserialized and invoking the gadget.

Since the POP chain was found previously that allows arbitrary file deletion, deleting the wp-config.php file using the PHP object injection could allow a malicious attacker to fully take over the WP site leading to RCE. The previously discussed gadget chain to direct RCE has been fixed on a brief look, however the same impact can be achieved by deleting the wp-config.php file.

The patch

The vendor added a stricter check for the serialized strings by adding the recursiveUrlDecode() function in the containsSerializedDataRegex() function.

The function strips any characters that are not: Letter (a-zA-Z), number (0-9), or any of the characters {}, :, ;, “, ‘, ., [, ], (, ), ,. After removing the extra characters, the serialized string check is effective again, patching the bypass.

Conclusion

A strict check for serialized content is very necessary in order to prevent malicious threat actors from injecting harmful content into the site and potentially taking over the site. In general, we recommend not using the deserialization process and using other data formats such as JSON to process more complex data.

Want to learn more about finding and fixing vulnerabilities?

Explore our Academy to master the art of finding and patching vulnerabilities within the WordPress ecosystem. Dive deep into detailed guides on various vulnerability types, from discovery tactics for researchers to robust fixes for developers. Join us and contribute to our growing knowledge base.

Timeline

31 December, 2024We initially received the vulnerability report from the researcher.
06 January, 2025We are able to validate the report (delay due to the reports queue and holiday) and reached out to the plugin vendor.
08 January, 2025GiveWP released version 3.19.4 to fix the vulnerability.
10 January, 2025Added the vulnerability to the database. Security advisory article published.

Help us make the Internet a safer place

Making the WordPress ecosystem more secure is a team effort, and we believe that plugin developers and security researchers should work together.

  • If you’re a plugin developer, join our mVDP program that makes it easier to report, manage and address vulnerabilities in your software.
  • If you’re a security researcher, join Patchstack Alliance to report vulnerabilities & earn rewards.

The latest in Security advisories

Looks like your browser is blocking our support chat widget. Turn off adblockers and reload the page.
crossmenu