You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/network-services-pentesting/pentesting-web/wordpress.md
+86Lines changed: 86 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -408,6 +408,88 @@ The `permission_callback` is a callback to function that checks if a given user
408
408
409
409
Of course, Wordpress uses PHP and files inside plugins are directly accessible from the web. So, in case a plugin is exposing any vulnerable functionality that is triggered just accessing the file, it's going to be exploitable by any user.
WordPress themes and plugins frequently expose AJAX handlers through the `wp_ajax_` and `wp_ajax_nopriv_` hooks. When the **_nopriv_** variant is used **the callback becomes reachable by unauthenticated visitors**, so any sensitive action must additionally implement:
414
+
415
+
1. A **capability check** (e.g. `current_user_can()` or at least `is_user_logged_in()`), and
416
+
2. A **CSRF nonce** validated with `check_ajax_referer()` / `wp_verify_nonce()`, and
417
+
3.**Strict input sanitisation / validation**.
418
+
419
+
The Litho multipurpose theme (< 3.1) forgot those 3 controls in the *Remove Font Family* feature and ended up shipping the following code (simplified):
***Unauthenticated access** – the `wp_ajax_nopriv_` hook is registered.
443
+
***No nonce / capability check** – any visitor can hit the endpoint.
444
+
***No path sanitisation** – the user–controlled `fontfamily` string is concatenated to a filesystem path without filtering, allowing classic `../../` traversal.
445
+
446
+
#### Exploitation
447
+
448
+
An attacker can delete any file or directory **below the uploads base directory** (normally `<wp-root>/wp-content/uploads/`) by sending a single HTTP POST request:
449
+
450
+
```bash
451
+
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
Because `wp-config.php` lives outside *uploads*, four `../` sequences are enough on a default installation. Deleting `wp-config.php` forces WordPress into the *installation wizard* on the next visit, enabling a full site take-over (the attacker merely supplies a new DB configuration and creates an admin user).
457
+
458
+
Other impactful targets include plugin/theme `.php` files (to break security plugins) or `.htaccess` rules.
459
+
460
+
#### Detection checklist
461
+
462
+
* Any `add_action( 'wp_ajax_nopriv_...')` callback that calls filesystem helpers (`copy()`, `unlink()`, `$wp_filesystem->delete()`, etc.).
463
+
* Concatenation of unsanitised user input into paths (look for `$_POST`, `$_GET`, `$_REQUEST`).
464
+
* Absence of `check_ajax_referer()` and `current_user_can()`/`is_user_logged_in()`.
0 commit comments