GiveWP Unauthenticated PHP Object Injection via Weak Serialized-Data Regex Check (CVE-2025-22777)
by SevDMG · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-22777
- Category
- web
- Affected product
- GiveWP – Donation Plugin and Fundraising Platform (WordPress plugin, 100,000+ active installs)
- Affected versions
- <= 3.19.3 (patched in 3.19.4)
- Disclosed
- 2026-07-06
- Patch status
- patched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07-06 |
| Author / Researcher | SevDMG |
| CVE / Advisory | CVE-2025-22777 |
| Category | web |
| Severity | Critical |
| CVSS Score | 9.8 (per NVD) |
| Status | PoC |
| Tags | givewp, wordpress, wordpress-plugin, php-object-injection, deserialization, unserialize, gadget-chain, cwe-502, php, unauthenticated |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | GiveWP – Donation Plugin and Fundraising Platform (WordPress plugin, 100,000+ active installs) |
| Versions Affected | <= 3.19.3 (patched in 3.19.4) |
| Language / Platform | PHP (target plugin), Python (PoC/exploit tooling) on WordPress |
| Authentication Required | No |
| Network Access Required | Yes (HTTP access to the donation form / admin-ajax.php endpoint) |
Summary
CVE-2025-22777 is an unauthenticated PHP Object Injection (CWE-502, Deserialization of Untrusted Data) vulnerability in the GiveWP WordPress donation plugin. GiveWP stores certain donor-supplied form field values as serialized PHP meta in the database and runs a regex check meant to confirm the value “looks like” a safe serialized string before it is later passed to PHP’s unserialize(); that regex check is weak and can be defeated by padding the payload with junk/gibberish characters, letting a crafted serialized object slip through and get deserialized. If a suitable gadget chain (a class with an exploitable magic method such as __destruct()/__wakeup()) is reachable in GiveWP or a co-installed plugin/theme, this results in arbitrary PHP object instantiation and potentially remote code execution, arbitrary file write/deletion, or other high-impact side effects — with no authentication required. This mirrored repository is an independent researcher’s work-in-progress PoC that builds a serialized “gadget” object (a FinalGadget/ChainGadget class chain targeting a filename property, injected via the donation form’s give_company field to admin-ajax.php?action=give_process_donation), but the actual HTTP exploit driver (exploit_cve2025-22777.py) ships with an empty payload = {} and no request is ever sent, and the more developed exploit_struct.py script’s exploit() function is truncated before it issues any HTTP request. As shipped, neither script performs a working end-to-end attack.
Vulnerability Details
Root Cause
GiveWP accepts certain donation-form fields (e.g. company name) and persists them as PHP-serialized donor meta. Before this data is later unserialized, the plugin performs a regex-based sanity check intended to reject anything that isn’t a “clean” serialized string. That regex is not strict enough: an attacker can interleave arbitrary junk bytes around/within a valid serialized-object payload, and the check still passes, so the tainted string reaches PHP’s unserialize() call path. This class of bug is a textbook CWE-502 (deserialization of untrusted data) — the fix in 3.19.4 tightens the validation so crafted/augmented serialized strings are rejected.
The PoC in this repo models this by hand-crafting a serialized gadget object and further “tweaking” its internal representation to bypass exactly this kind of loose validation, e.g. in test2_phpserializer.py:
| |
The intended injection point is the donation form’s give_company parameter, submitted to WordPress admin-ajax.php with action=give_process_donation:
| |
Attack Vector
- Attacker locates a WordPress site running a vulnerable GiveWP version (<= 3.19.3) with a public donation form.
- Attacker crafts a malicious serialized PHP object (a “gadget”) targeting a class with an exploitable magic method reachable via GiveWP or another installed plugin/theme.
- Attacker submits the donation form (directly or via the
admin-ajax.phpgive_process_donationaction) with the serialized payload placed in a field such asgive_company, padded with extra bytes so the weak validation regex still accepts it as “safe” serialized data. - GiveWP stores this value as donor meta and later calls
unserialize()on it without authentication being required at any point. - If a usable gadget chain is present, the deserialization triggers the gadget’s magic method, leading to code execution, file write/deletion, or other object-injection-driven impact.
Impact
Full unauthenticated PHP Object Injection on any public-facing GiveWP donation form; depending on available gadget chains on the target site (GiveWP itself, other plugins, or the theme), this can escalate to remote code execution, arbitrary file read/write/delete, privilege escalation, or site takeover — all without any prior authentication, on a plugin with 100,000+ active installs.
Environment / Lab Setup
- WordPress install with GiveWP plugin <= 3.19.3 (vulnerable) — e.g. via a local WP dev environment (wp-env, LocalWP, Docker WordPress image) with GiveWP installed and a public donation form configured.
- Attacker host: Python 3.x with the packages in requirements.txt:
phpserialize==1.3
colorama==0.4.6
requests==2.32.5
faker>=25.0.0
- Optional: Burp Suite / proxy for request interception (exploit_struct.py accepts a --proxy argument).
Proof of Concept
PoC Script
See
exploit_cve2025-22777.py,exploit_struct.py,test1_with_no_phpserialize.py,test2_phpserializer.py, andtest_colorama.pyin this folder.
| |
Detection & Indicators of Compromise
- POST requests to /wp-admin/admin-ajax.php with action=give_process_donation where donor fields
(give_company, give_first, give_last, etc.) contain PHP serialization markers (e.g. O:<len>:"ClassName",
s:<len>:, a:<len>:{) or unusual non-printable/binary byte sequences padding a serialized-looking string.
- Donor/meta database rows (givewp donor meta tables) containing serialized values with embedded
non-ASCII/control-byte padding around otherwise well-formed PHP serialization syntax.
- Unexpected PHP errors/warnings referencing unserialize() or __wakeup()/__destruct() around donation
submission timestamps.
Signs of compromise:
- Anomalous donation submissions with non-standard characters in the company/name fields.
- New or modified files on the webserver following a donation submission (indicative of a file-write gadget).
- PHP error logs showing failed unserialize() calls or object instantiation of unexpected classes.
- Unexpected outbound connections or new admin users appearing shortly after suspicious donation activity.
Remediation
| Action | Detail |
|---|---|
| Primary fix | Update GiveWP to version 3.19.4 or later, which tightens the serialized-data validation to prevent the regex bypass. |
| Interim mitigation | If upgrading is not immediately possible: disable/restrict the public donation form, add a WAF rule blocking requests to admin-ajax.php (action=give_process_donation) containing PHP serialization markers (O:, a:, s: patterns) in form fields, and monitor donor meta for anomalous serialized content. |
References
- Source repository
- GitHub Advisory GHSA-h6pf-2cgw-xppm
- Patchstack: Critical Vulnerability Patched in GiveWP Plugin
Notes
Mirrored from https://github.com/SevDMG/CVE-2025-22777-GiveWP-Plugin-PHP-Object-Injection-Point-PoC- on 2026-07-06. The repository is explicitly marked by its author as a work-in-progress PoC: exploit_cve2025-22777.py ships with an empty payload = {} and never actually sends a functional request, and exploit_struct.py’s exploit() function is truncated before any HTTP request is issued (no session.post(...) call, no CLI argument wiring via argparse). The gadget-building/serialization logic (test2_phpserializer.py) is genuine and illustrates the real bypass technique (padding a serialized object with junk bytes to slip past GiveWP’s weak validation regex), but there is no complete, runnable end-to-end exploit in this repo as of the mirrored commit. Treat this as a conceptual/educational reference for the vulnerability mechanism rather than a functional weaponized exploit.
| |