My site – this site – was exploited due to an unpatched vulnerability. The wp2shell vulnerability. The very same vulnerability I patched for many client sites just a few weeks ago.
This was also somewhat intentional. I had a very busy period in life, and so I half-decided to leave the site open as a honeypot, interested to see what happens when a site is exploited, how long it takes to be exploited, how difficult it is to clean up (but knowing I have good backups.)
But also: my intentionally over-engineered deployment process meant I hadn’t the chance to update site.
Timeline for exploit and cleanup
- WordPress 7.0.2 (and it’s backports) came out on July 17, 2026 (the release post was published at 19:45 UTC+1).
- The fist admin user account on my site was registered on 2026-08-07 13:22 (UTC+1).
- New admin accounts were created right up until 2026-08-24 18:10 (UTC+1)
- The site was cleaned up and patched on 2026-08-25, around 12:00 (UTC+1)
Findings
- 106 new admin accounts were created. According to Claude:
“37 of the 106 rogue accounts have live, non-empty session_tokens — meaning valid auth cookies were issued and used, not just orphaned rows. This indicates the attacker(s) actually logged in and held working admin sessions, some as recently as 2026‑08‑24.” - 3 new posts created, each using one of those accounts.
- My admin account password was reset.
- 5 new posts created using my account.
- 2 pingbacks from those 5 new posts.
- 855 orphaned post meta.
- 116 new customizer changesets.
- 116 new
requestposts (not a valid CPT on this site). - 0 new themes, plugins, mu-plugins, or file system changes.
Cleanup process
I use restic for my backups, which includes a database dump, so the first thing I did was grab a known-good database dump and diff it against a recent one. I had to restore it locally and re-export using extended inserts (well, just using wp db export). That let me see every new row easily, which is only possible given the low frequency of changes in the DB. That helped identify the unexpected changes outlined above.
Claude also helped in reviewing. I fed it Pantheon’s audit skill (to use a reference, since I’m not hosted there) which helped it find a few things I missed in my manual review. It’s effective at reviewing a db dump from before and after and generating a report.
After I cleaned up the posts and users, restic diff confirmed that there were no unexpected file changes – no web shells, uploads, etc.
# Compare known-good snapshot to infected snapshot
restic diff 11c75f49 5a7716ba
At this point, I deployed the upgrade (7.0.4 at first, 7.1 later).
Given my account’s password was changed, I had already changed it to gain access to the site again, but here is also where I would have changed any other legit account passwords.
My account also had an Application Password, which was unused, so I deleted that, as well as a few other API connections in the database. And I rotated the wp-config salts and my database password.
Lastly, cleaning up the orphan posts and meta needed a few commands.
Additional Clean up Commands
# Removes oEmbed cache, since some of the inserted posts had oEmdebs. Legit oEmbeds will have their cache regenerated automatically.
wp post delete $(wp post list --post_type=oembed_cache --format=ids) --force
# Removes customizer changesets & `request` posts. This may be too loosely scoped for sites that use the Customizer or a `request` post type.
wp post delete --force $(wp post list --post_type=customize_changeset --post_status=any --field=ID) \
$(wp db query --silent "SELECT ID FROM wp_posts WHERE post_type='request' AND post_status='parse'" --skip-column-names)
# Clean up orphaned post meta. Again - loosely scoped, may delete post meta not related to this incident.
wp db query "DELETE pm FROM wp_postmeta pm
LEFT JOIN wp_posts p ON p.ID = pm.post_id
WHERE p.ID IS NULL;"
Would I do this again?
No.
In hindsight, it was irresponsible to leave a public site, despite its low traffic, open to known exploit like that. Even though the cleanup was easy, and damage to my site null, there are other potential implications, such as impact to visitors via XSS.
I’ve already added a new Github Action to automate minor releases nightly, to avoid this situation again.
Exploit Artifacts
Below are some dumps and screenshots of the things I’d found, in case it’s interesting.



wp db query "SELECT * FROM wp_postmeta ORDER BY post_id DESC LIMIT 20"
meta_id post_id meta_key meta_value
7769 1898338624 _menu_item_orphaned 1785775487
7768 1898338624 _menu_item_url https://example.invalid/
7767 1898338624 _menu_item_xfn
7766 1898338624 _menu_item_classes a:1:{i:0;s:0:"";}
7765 1898338624 _menu_item_target
7764 1898338624 _menu_item_object custom
7763 1898338624 _menu_item_object_id 1898338624
7762 1898338624 _menu_item_menu_item_parent 0
7761 1898338624 _menu_item_type custom
7607 1898174433 _menu_item_orphaned 1784999426
7606 1898174433 _menu_item_url https://github.com/dinosn/wp2shell-lab
7605 1898174433 _menu_item_xfn
7604 1898174433 _menu_item_classes a:1:{i:0;s:0:"";}
7603 1898174433 _menu_item_target
7602 1898174433 _menu_item_object custom
7601 1898174433 _menu_item_object_id 1898174433
7600 1898174433 _menu_item_menu_item_parent 0
7599 1898174433 _menu_item_type custom
7949 1897897392 _menu_item_orphaned 1786127074
7948 1897897392 _menu_item_url https://wp.org/
wp db query "SELECT * FROM wp_posts WHERE post_type='oembed_cache' ORDER BY ID DESC LIMIT 5"
ID post_author post_date post_date_gmt post_content post_title post_excerpt post_status comment_status ping_status post_password post_name to_ping pinged post_modified post_modified_gmt post_content_filtered post_parent guid menu_order post_type post_mime_type comment_count
4503 0 2026-08-24 20:10:21 2026-08-24 18:10:21 <blockquote class="wp-embedded-content" data-secret="221T9hSDyS"><a href="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/">A few things from the first WordCamp Toulouse</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; visibility: hidden;" title="“A few things from the first WordCamp Toulouse” — Jesse Dyck" src="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/embed/#?secret=0zdR4DeA6q#?secret=221T9hSDyS" data-secret="221T9hSDyS" width="500" height="282" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> publish open open c4a30a6011a84080d23d9ec406d98dc2 2026-08-24 20:10:21 2026-08-24 18:10:21 0 https://jessedyck.me/2026/08/c4a30a6011a84080d23d9ec406d98dc2/ 0 oembed_cache 0
4502 0 2026-08-24 20:10:21 2026-08-24 18:10:21 <blockquote class="wp-embedded-content" data-secret="mPoZANDG1x"><a href="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/">A few things from the first WordCamp Toulouse</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; visibility: hidden;" title="“A few things from the first WordCamp Toulouse” — Jesse Dyck" src="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/embed/#?secret=m7i3hJ2l7g#?secret=mPoZANDG1x" data-secret="mPoZANDG1x" width="500" height="282" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> publish open open ec2bccd57cae769c6cdcc7cd622a4605 2026-08-24 20:10:21 2026-08-24 18:10:21 0 https://jessedyck.me/2026/08/ec2bccd57cae769c6cdcc7cd622a4605/ 0 oembed_cache 0
4498 0 2026-08-24 15:33:16 2026-08-24 13:33:16 <blockquote class="wp-embedded-content" data-secret="HDPkzmYQ8j"><a href="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/">A few things from the first WordCamp Toulouse</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; visibility: hidden;" title="“A few things from the first WordCamp Toulouse” — Jesse Dyck" src="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/embed/#?secret=mqfTKdymdM#?secret=HDPkzmYQ8j" data-secret="HDPkzmYQ8j" width="500" height="282" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> publish open open 450f93319926b4531cb9cbdb8e732821 2026-08-24 15:33:16 2026-08-24 13:33:16 0 https://jessedyck.me/2026/08/450f93319926b4531cb9cbdb8e732821/ 0 oembed_cache 0
4494 0 2026-08-24 05:27:18 2026-08-24 03:27:18 <blockquote class="wp-embedded-content" data-secret="t0uDutq8rf"><a href="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/">A few things from the first WordCamp Toulouse</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; visibility: hidden;" title="“A few things from the first WordCamp Toulouse” — Jesse Dyck" src="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/embed/#?secret=POFdh0xvrH#?secret=t0uDutq8rf" data-secret="t0uDutq8rf" width="500" height="282" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> publish open open 612ccc82e1c199560c83543ebcddaada 2026-08-24 05:27:18 2026-08-24 03:27:18 0 https://jessedyck.me/2026/08/612ccc82e1c199560c83543ebcddaada/ 0 oembed_cache 0
4490 0 2026-08-24 04:48:27 2026-08-24 02:48:27 <blockquote class="wp-embedded-content" data-secret="XfSw5mGFgC"><a href="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/">A few things from the first WordCamp Toulouse</a></blockquote><iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; visibility: hidden;" title="“A few things from the first WordCamp Toulouse” — Jesse Dyck" src="https://jessedyck.me/2025/05/a-few-things-from-the-first-wordcamp-toulouse/embed/#?secret=l9IlWB1WKW#?secret=XfSw5mGFgC" data-secret="XfSw5mGFgC" width="500" height="282" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe> publish open open da35153ca103c66ab1743707a8d73737 2026-08-24 04:48:27 2026-08-24 02:48:27 0 https://jessedyck.me/2026/08/da35153ca103c66ab1743707a8d73737/ 0 oembed_cache 0
wp db query "SELECT * FROM wp_posts WHERE post_type='request' ORDER BY ID DESC LIMIT 5"
ID post_author post_date post_date_gmt post_content post_title post_excerpt post_status comment_status ping_status post_password post_name to_ping pinged post_modified post_modified_gmt post_content_filtered post_parent guid menu_order post_type post_mime_type comment_count
4504 1 2020-01-01 00:00:00 2020-01-01 00:00:00 reentry parse closed closed reentry-21 2026-08-24 20:10:24 2026-08-24 18:10:240 0 request 0
4497 1 2020-01-01 00:00:00 2020-01-01 00:00:00 parse parse parse closed closed parse-73 2026-08-24 15:33:18 2026-08-24 13:33:180 0 request 0
4493 1 2020-01-01 00:00:00 2020-01-01 00:00:00 parse parse parse closed closed parse-72 2026-08-24 05:27:20 2026-08-24 03:27:200 0 request 0
4489 1 2020-01-01 00:00:00 2020-01-01 00:00:00 parse parse parse closed closed parse-71 2026-08-24 04:48:29 2026-08-24 02:48:290 0 request 0
4487 1 2020-01-01 00:00:00 2020-01-01 00:00:00 parse parse parse closed closed parse-70 2026-08-23 22:54:08 2026-08-23 20:54:080 0 request 0
Listing of all the new administrator accounts:
+-------------------+--------------------------------------+---------------------+
| user_login | user_email | user_registered |
+-------------------+--------------------------------------+---------------------+
| 00c18f1803bd44f | 210a@wp2shell.invalid | 2026-08-20 15:24:29 |
| 0f9c4c159edc | 0f9c4c159edc@google.com | 2026-07-23 05:14:25 |
| 3db94173e0f5272 | e294@wp2shell.invalid | 2026-08-18 23:36:35 |
| 5e4c82192acf | 5e4c82192acf@google.com | 2026-08-09 10:18:05 |
| ABC_bf8f120e72 | ABC_bf8f120e72@local.invalid | 2026-08-15 20:32:40 |
| Angelica | angelica1551@yahoo.com | 2026-08-22 11:32:06 |
| b15cada829a601e | ffb2@wp2shell.invalid | 2026-08-20 16:51:22 |
| b22998bb4ac4e4c | 4cfb@wp2shell.invalid | 2026-08-18 23:36:22 |
| b68c95ab647f | b68c95ab647f@google.com | 2026-07-29 15:32:50 |
| bob_023c92f1d067 | bob_023c92f1d067@bobresearchlabs.com | 2026-08-03 00:32:46 |
| bob_34921f404960 | bob_34921f404960@bobresearchlabs.com | 2026-08-08 13:36:22 |
| bob_495ebc7c6dff | bob_495ebc7c6dff@bobresearchlabs.com | 2026-08-04 00:44:17 |
| bob_642d8e9060b6 | bob_642d8e9060b6@bobresearchlabs.com | 2026-08-01 00:39:15 |
| bob_96139ff068b4 | bob_96139ff068b4@bobresearchlabs.com | 2026-08-02 00:33:35 |
| bob_a2646dfc87a8 | bob_a2646dfc87a8@bobresearchlabs.com | 2026-07-31 06:28:49 |
| bob_abbdfc5655f4 | bob_abbdfc5655f4@bobresearchlabs.com | 2026-07-30 12:26:28 |
| bob_b940fb440a95 | bob_b940fb440a95@bobresearchlabs.com | 2026-07-31 00:33:56 |
| bob_c92d68788590 | bob_c92d68788590@bobresearchlabs.com | 2026-08-12 11:19:03 |
| bob_ecb03085454c | bob_ecb03085454c@bobresearchlabs.com | 2026-08-21 14:23:06 |
| bob_f4e4d159bc49 | bob_f4e4d159bc49@bobresearchlabs.com | 2026-08-08 09:00:21 |
| ca48243d23e83ab | adc6@wp2shell.invalid | 2026-08-20 16:51:34 |
| cc2751e01057426 | bca9@wp2shell.invalid | 2026-08-20 15:24:16 |
| ec0982625f21 | ec0982625f21@google.com | 2026-07-22 15:25:17 |
| guanzhoi_0161 | guanzhoi_0161@exam.com | 2026-08-13 10:13:21 |
| jessedycks9ee4bd | jessedycks9ee4bd@jessedyck.me | 2026-08-20 05:00:58 |
| jessedycksa1d0d4 | jessedycksa1d0d4@jessedyck.me | 2026-08-18 00:54:48 |
| jessedycksbdb4cc | jessedycksbdb4cc@jessedyck.me | 2026-08-19 23:05:26 |
| jessedycksc47e81 | jessedycksc47e81@jessedyck.me | 2026-08-21 01:04:27 |
| jessedyckse49ac0 | jessedyckse49ac0@jessedyck.me | 2026-08-11 00:00:16 |
| JLG_795e386f01fa | JLG_795e386f01fa@wp2shell.local | 2026-08-01 16:21:38 |
| JLG_c067705fc040 | JLG_c067705fc040@wp2shell.local | 2026-08-12 05:10:03 |
| JLG_f6b94c39ba67 | JLG_f6b94c39ba67@wp2shell.local | 2026-07-25 17:10:26 |
| kacak | kacak@mailinator.com | 2026-08-22 01:11:45 |
| Nx_97865405ab4d | Nx_97865405ab4d@nx.invalid | 2026-08-03 17:43:21 |
| Nx_d7c7e4cd7053 | Nx_d7c7e4cd7053@nx.invalid | 2026-08-03 15:51:08 |
| siteadmin | siteadmin@wp2shell.invalid | 2026-08-22 17:58:42 |
| w2s_0d44761fc704 | w2s_0d44761fc704@wp2shell.local | 2026-07-22 19:36:59 |
| w2s_2f73dcf8075b | w2s_2f73dcf8075b@wp2shell.local | 2026-08-02 17:37:58 |
| w2s_3d8ccafdb74b | w2s_3d8ccafdb74b@wp2shell.local | 2026-08-03 13:23:10 |
| w2s_3dd7102b9051 | w2s_3dd7102b9051@google.local | 2026-07-24 08:41:17 |
| w2s_48f400705d90 | w2s_48f400705d90@wp2shell.local | 2026-08-03 16:32:15 |
| w2s_52c1f0d8bdbe | w2s_52c1f0d8bdbe@wp2shell.local | 2026-08-24 02:48:30 |
| w2s_54ae3de4504f | w2s_54ae3de4504f@wp2shell.local | 2026-08-24 03:27:20 |
| w2s_570aa44844ae | w2s_570aa44844ae@wp2shell.local | 2026-07-23 02:06:47 |
| w2s_5952fddc24 | w2s_5952fddc24@local.invalid | 2026-08-20 18:24:26 |
| w2s_5c8b28c7abf2 | w2s_5c8b28c7abf2@wp2shell.invalid | 2026-08-11 05:01:31 |
| w2s_75a45e47cc1e | w2s_75a45e47cc1e@wp2shell.local | 2026-08-24 13:33:18 |
| w2s_83adda333088 | w2s_83adda333088@wp2shell.local | 2026-08-05 14:59:15 |
| w2s_a0b0e6f772ce | w2s_a0b0e6f772ce@wp2shell.local | 2026-08-01 16:24:19 |
| w2s_ad169a42c573 | w2s_ad169a42c573@wp2shell.local | 2026-07-24 07:53:12 |
| w2s_b422326167b6 | w2s_b422326167b6@wp2shell.local | 2026-07-26 22:46:00 |
| w2s_b8452d0d8d09 | w2s_b8452d0d8d09@shellcode.lol | 2026-07-29 13:57:49 |
| w2s_bee16425bd14 | w2s_bee16425bd14@wp2shell.local | 2026-08-02 18:59:53 |
| w2s_d27af94d6f61 | w2s_d27af94d6f61@wp2shell.local | 2026-07-22 23:47:36 |
| w2s_ebfc9da3e604 | w2s_ebfc9da3e604@wp2shell.local | 2026-08-06 00:52:13 |
| w2s_f7c968d7f0 | w2s_f7c968d7f0@local.invalid | 2026-08-06 05:11:59 |
| wp_admin_5d0f00 | wp_admin_5d0f00@local.host | 2026-08-20 17:22:30 |
| wp_admin_ce2b7d | wp_admin_ce2b7d@local.host | 2026-07-31 13:36:39 |
| wp_service_309af8 | wp_service_309af8@service.localhost | 2026-08-16 03:47:26 |
| wp_service_48897d | wp_service_48897d@service.localhost | 2026-08-24 18:10:24 |
| wp_service_592e2c | wp_service_592e2c@service.localhost | 2026-08-21 22:51:54 |
| wp_service_5ae12f | wp_service_5ae12f@service.localhost | 2026-08-21 21:01:56 |
| wp_service_5b5fd0 | wp_service_5b5fd0@service.localhost | 2026-08-22 16:10:16 |
| wp_service_6252ee | wp_service_6252ee@service.localhost | 2026-08-21 23:30:48 |
| wp_service_6aeae3 | wp_service_6aeae3@service.localhost | 2026-08-19 06:08:04 |
| wp_service_82648e | wp_service_82648e@service.localhost | 2026-08-18 21:03:10 |
| wp_service_858e31 | wp_service_858e31@service.localhost | 2026-08-20 03:07:00 |
| wp_service_99d353 | wp_service_99d353@service.localhost | 2026-08-18 15:03:54 |
| wp_service_a0a20e | wp_service_a0a20e@service.localhost | 2026-08-20 00:45:02 |
| wp_service_ac3349 | wp_service_ac3349@service.localhost | 2026-08-16 12:45:30 |
| wp_service_bce929 | wp_service_bce929@service.localhost | 2026-08-20 22:24:01 |
| wp_service_c3f922 | wp_service_c3f922@service.localhost | 2026-08-14 13:47:18 |
| wp_service_d17901 | wp_service_d17901@service.localhost | 2026-08-21 22:59:40 |
| wp_service_d56095 | wp_service_d56095@service.localhost | 2026-08-17 01:33:16 |
| wp_service_d7f61c | wp_service_d7f61c@service.localhost | 2026-08-18 13:20:41 |
| wp_service_ee2d11 | wp_service_ee2d11@service.localhost | 2026-08-17 14:37:47 |
| wp_service_fa0170 | wp_service_fa0170@service.localhost | 2026-08-16 22:03:23 |
| wp069ea1d61 | wp069ea1d61@jessedyck.me | 2026-08-04 10:49:48 |
| wp2_041a0c | wp2_041a0c@wp2shell.invalid | 2026-07-21 22:01:08 |
| wp2_06fa30 | wp2_06fa30@wp2shell.invalid | 2026-08-07 13:22:47 |
| wp2_0b265bc1 | wp2_0b265bc1@wp2shell.invalid | 2026-08-19 02:30:18 |
| wp2_1e55a8 | wp2_1e55a8@wp2shell.invalid | 2026-08-20 05:54:39 |
| wp2_280a56c4 | wp2_280a56c4@wp2shell.invalid | 2026-08-20 15:15:28 |
| wp2_469d12 | wp2_469d12@wp2shell.invalid | 2026-08-10 05:36:24 |
| wp2_5034a419 | wp2_5034a419@wp2shell.invalid | 2026-08-17 01:14:21 |
| wp2_59e814 | wp2_59e814@wp2shell.invalid | 2026-08-12 10:53:24 |
| wp2_5fb2cb | wp2_5fb2cb@wp2shell.invalid | 2026-08-10 06:23:09 |
| wp2_66a512 | wp2_66a512@wp2shell.invalid | 2026-08-03 17:44:05 |
| wp2_6a21ac | wp2_6a21ac@wp2shell.invalid | 2026-08-10 17:57:19 |
| wp2_79630a | wp2_79630a@wp2shell.invalid | 2026-08-04 05:54:48 |
| wp2_92c8a3 | wp2_92c8a3@wp2shell.invalid | 2026-08-11 21:46:44 |
| wp2_9ef752fd | wp2_9ef752fd@wp2shell.invalid | 2026-08-21 17:54:33 |
| wp2_ab8d45 | wp2_ab8d45@wp2shell.invalid | 2026-08-05 18:34:24 |
| wp2_b4d31b | wp2_b4d31b@wp2shell.invalid | 2026-08-16 13:14:02 |
| wp2_be7206 | wp2_be7206@wp2shell.invalid | 2026-08-18 10:49:09 |
| wp2_c5d1fd | wp2_c5d1fd@wp2shell.invalid | 2026-08-19 16:13:56 |
| wp2_c77f55 | wp2_c77f55@wp2shell.invalid | 2026-08-06 18:33:01 |
| wp2_cabc68 | wp2_cabc68@wp2shell.invalid | 2026-08-10 20:41:39 |
| wp2_cf026a | wp2_cf026a@wp2shell.invalid | 2026-08-04 01:57:33 |
| wp2_cf1d3d | wp2_cf1d3d@wp2shell.invalid | 2026-08-03 16:44:47 |
| wp2_d079ef | wp2_d079ef@wp2shell.invalid | 2026-08-23 20:54:08 |
| wp2_d3b2587daa9c | wp2_d3b2587daa9c@wp2shell.invalid | 2026-08-17 21:50:51 |
| wp2_ea539c | wp2_ea539c@wp2shell.invalid | 2026-08-16 10:12:43 |
| wp2_ff781cfe | wp2_ff781cfe@wp2shell.invalid | 2026-08-08 06:10:25 |
| xaver | xaver@jessedyck.me | 2026-08-16 23:04:20 |
| yun_11 | yun_11@wp2shell.invalid | 2026-08-07 11:58:00 |
+-------------------+--------------------------------------+---------------------+

Leave a Reply