š¢ Calling all Vulnerability Researchers and Bug Bounty Hunters! š¢
šĀ Participate in the SQLsplorer Challenge! Now through September 22, 2025, all SQL Injection vulnerabilities in software with at least 25 active installs are considered in-scope for all researchers, regardless of researcher tier AND earn a 20% bonus on all SQL Injection vulnerability submissions.
On August 17th, 2025, we received a submission for an authenticated PHP Object Injection vulnerability in Fluent Forms, a WordPress plugin with more than 600,000 active installations. This vulnerability can be leveraged via an existing POP chain present in the plugin to read arbitrary files on the server, which may contain sensitive information.
Props to Webbernaut who discovered and responsibly reported this vulnerability through the Wordfence Bug Bounty Program. This researcher earned a bounty of $1,729.00 for this discovery. Our mission is to secure WordPress through defense in depth, which is why we are investing in quality vulnerability research and collaborating with researchers of this caliber through our Bug Bounty Program. We are committed to making the WordPress ecosystem more secure through the detection and prevention of vulnerabilities, which is a critical element to our multi-layered approach to security.
All Wordfence Premium, Wordfence Care, and Wordfence Response customers, as well as those using the free version of our plugin, are protected against any exploits targeting this vulnerability by the Wordfence firewallās built-in Generic Object Injection protection.
We provided full disclosure details to the WPManageNinja team instantly through our Wordfence Vulnerability Management Portal on August 20, 2025. The developer released the patch on August 27, 2025. We would like to commend the WPManageNinja team for their prompt response and timely patch.
We urge users to update their sites with the latest patched version of Fluent Forms, version 6.1.2 at the time of this writing, as soon as possible.
Vulnerability Summary from Wordfence Intelligence
How Does PHP Object Injection Work?
Before we dive into the technical details of this vulnerability, weāll provide some background on what exactly PHP Object Injection is and how it works. This has been covered in more depth in a previous article we wrote detailing anotherĀ PHP Object Injection vulnerability.
PHP uses serialization to store complex data. Serialized data often looks like this:
a:2:{s:11:"productName";s:5:"apple";s:7:"price";i:10;}
In this payload,Ā productNameĀ is set to āappleā andĀ priceĀ is set to 10.
Serialized data is useful for storing settings in bulk, and WordPress uses it for many of its settings. However, it can also cause a security issue because it can be used to store PHP objects.
What Are PHP Objects?
Most modern PHP code is object oriented, where code is organized into āclassesā. Classes serve as templates with variables (called āpropertiesā) and functions (called āmethodsā). Programs create āobjectsā from these classes, resulting in more reusable, maintainable, scalable, and robust code.
For example, an online store might use a single class for products with properties likeĀ $priceĀ andĀ $productName, creating different objects for each product. Each object could use the same method to calculate tax, but with different prices and names.
If a plugin unserializes user-provided data without sanitizing it, an attacker could inject a payload that becomes a PHP object when unserialized. While a simple PHP object isnāt dangerous, the situation changes if the class includes magic methods.
What Are Magic Methods?
Magic methods are special functions in a class that define behavior during certain events. For example, theĀ __destructĀ method is used to clean up when an object is no longer needed.
Hereās a simple example of a vulnerable class that calculates product prices, stores a log, and deletes the log when there are no remaining references to the object:
class Product {
public $price;
public $productName;
public $savedPriceFile;
function __construct( $price, $productName ) {
$this->price = $price;
$this->productName = $productName;
$this->savedPriceFile = $productName . "pricefile.log";
}
function calculateTotal( $quantity ) {
$total = $this->price * $quantity;
echo $total;
file_put_contents( $this->savedPriceFile, $total );
}
function __destruct() {
unlink( $this->savedPriceFile );
}
}
If this code is executed on a site with a PHP Object Injection vulnerability, an attacker could exploit it to delete arbitrary files. For example, this payload deletes theĀ wp-config.phpĀ file:
O:7:"Product":3:{s:5:"price";i:2;s:11:"productName";s:6:"apples";s:14:"savedPriceFile";s:13:"wp-config.php";}
This would inject a Product object withĀ $productNameĀ set to āapplesā,Ā $priceĀ set to 2, andĀ $savedPriceFileĀ set to āwp-config.phpā. Even though the object might not be used by anything else, eventually theĀ __destructĀ method would run and delete the file specified inĀ $savedPriceFile. In this case, deletingĀ wp-config.phpĀ would reset the site, potentially allowing an attacker to take over by connecting it to a remote database they control.
Technical Analysis
Fluent Forms is a WordPress form builder plugin that allows users to create various types of forms with a simple, user-friendly drag-and-drop builder.
Fluent Forms offers various dynamic smart codes that can be used in the form builder.
For example, the administrator can add the following text to the formās introduction html:
Hello {user.meta.first_name},
And when a logged-in user views the form, they see the following message:
Hello Bob,
Examining the code reveals that the theme uses the parseUserProperties() function in the FluentFormAppServicesFormBuilderEditorShortcodeParser class to parse user smart codes.
private static function parseUserProperties($value, $form = null)
{
if ($user = wp_get_current_user()) {
$prop = substr(str_replace(['{', '}'], '', $value), 5);
if (false !== strpos($prop, 'meta.')) {
$metaKey = substr($prop, strlen('meta.'));
$userId = $user->ID;
$data = get_user_meta($userId, $metaKey, true);
$data = maybe_unserialize($data);
if (!is_array($data)) {
return esc_html($data);
}
return esc_html(implode(',', $data));
}
return esc_html($user->{$prop});
}
return '';
}
The function unserializes the user meta value using the maybe_unserialize() function, which can make it possible for the attacker to perform a PHP Object Injection by storing a malicious serialized object in their own user meta.
The plugin contains a POP chain that reads arbitrary files. Ultimately, this makes it possible for authenticated attackers with minimal access, like subscribers, to read any arbitrary file on the server, including the siteās wp-config.php file, which contains the database credentials as well as keys and salts for cryptographic security.
The Patch
The vendor of the Fluent Forms plugin patched this issue by adding the Helper::safeUnserialize() function, which uses the unserialize() function with allowed_classes false parameter. This ensures that the object does not contain any classes.
private static function parseUserProperties($value, $form = null)
{
if ($user = wp_get_current_user()) {
$prop = substr(str_replace(['{', '}'], '', $value), 5);
if (false !== strpos($prop, 'meta.')) {
$metaKey = substr($prop, strlen('meta.'));
$metaKey = sanitize_key($metaKey);
$allowedKeys = self::getAllowedUserMetaKeys($form);
if (!in_array($metaKey, $allowedKeys, true)) {
return '';
}
$userId = $user->ID;
$data = get_user_meta($userId, $metaKey, true);
$data = Helper::safeUnserialize($data);
if (!is_array($data)) {
return esc_html($data);
}
return esc_html(implode(',', $data));
}
return esc_html($user->{$prop});
}
return '';
}
public static function safeUnserialize($data)
{
if (is_serialized($data)) { // Don't attempt to unserialize data that wasn't serialized going in.
return @unserialize(trim($data), ['allowed_classes' => false]);
}
return $data;
}
Disclosure Timeline
August 17, 2025 ā We received the submission for the PHP Object Injection vulnerability in Fluent Forms via the Wordfence Bug Bounty Program.
August 20, 2025 ā We validated the report and confirmed the proof-of-concept exploit.
August 20, 2025 ā Full disclosure details were sent instantly to the vendor through our Wordfence Vulnerability Management Portal.
August 27, 2025 ā The vendor acknowledged the report and began working on a fix.
August 27, 2025 ā The partially patched version of the plugin, 6.1.0, was released.
August 29, 2025 ā The fully patched version of the plugin, 6.1.2, was released.
Conclusion
In this blog post, we detailed an Arbitrary File Read vulnerability within the Fluent Forms plugin affecting versions 5.1.16 through 6.1.1. This vulnerability allows authenticated threat actors to read arbitrary files, which can contain sensitive information. The vulnerability has been addressed in version 6.1.2 of the plugin.
We encourage WordPress users to verify that their sites are updated to the latest patched version of Fluent Forms as soon as possible considering the critical nature of this vulnerability.
All Wordfence users, including those running Wordfence Premium, Wordfence Care, and Wordfence Response, as well as sites running the free version of Wordfence, are fully protected against this vulnerability.
If you know someone who uses this plugin on their site, we recommend sharing this advisory with them to ensure their site remains secure, as this vulnerability poses a significant risk.
The post 600,000 WordPress Sites Affected by PHP Object Injection Vulnerability in Fluent Forms WordPress Plugin appeared first on Wordfence.