Update wordpress.md

This commit is contained in:
SirBroccoli 2025-10-04 11:00:33 +02:00 committed by GitHub
parent cf8c612244
commit b97cee4395
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -447,15 +447,6 @@ Detection checklist
- Review REST registrations for privileged callbacks that lack robust `permission_callback` checks and instead rely on request headers.
- Look for usages of core user-management functions (`wp_insert_user`, `wp_create_user`) inside REST handlers that are gated only by header values.
Hardening
- Never derive authentication or authorization from client-controlled headers.
- If a reverse proxy must inject identity, terminate trust at the proxy and strip inbound copies (e.g., `unset X-Wcpay-Platform-Checkout-User` at the edge), then pass a signed token and verify it server-side.
- For REST routes performing privileged actions, require `current_user_can()` checks and a strict `permission_callback` (do NOT use `__return_true`).
- Prefer first-party auth (cookies, application passwords, OAuth) over header “impersonation”.
References: see the links at the end of this page for a public case and broader analysis.
### Unauthenticated Arbitrary File Deletion via wp_ajax_nopriv (Litho Theme <= 3.0)
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:
@ -511,31 +502,6 @@ Other impactful targets include plugin/theme `.php` files (to break security plu
* Concatenation of unsanitised user input into paths (look for `$_POST`, `$_GET`, `$_REQUEST`).
* Absence of `check_ajax_referer()` and `current_user_can()`/`is_user_logged_in()`.
#### Hardening
```php
function secure_remove_font_family() {
if ( ! is_user_logged_in() ) {
wp_send_json_error( 'forbidden', 403 );
}
check_ajax_referer( 'litho_fonts_nonce' );
$fontfamily = sanitize_file_name( wp_unslash( $_POST['fontfamily'] ?? '' ) );
$srcdir = trailingslashit( wp_upload_dir()['basedir'] ) . 'litho-fonts/' . $fontfamily;
if ( ! str_starts_with( realpath( $srcdir ), realpath( wp_upload_dir()['basedir'] ) ) ) {
wp_send_json_error( 'invalid path', 400 );
}
// … proceed …
}
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_family' );
// 🔒 NO wp_ajax_nopriv_ registration
```
> [!TIP]
> **Always** treat any write/delete operation on disk as privileged and double-check:
> • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via `realpath()` plus `str_starts_with()`).
---
### Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")
@ -565,12 +531,6 @@ Why its exploitable
- If a user previously had higher privileges saved in `_asenha_view_admin_as_original_roles` and was downgraded, they can restore them by hitting the reset path.
- In some deployments, any authenticated user could trigger a reset for another username still present in `viewing_admin_as_role_are` (broken authorization).
Attack prerequisites
- Vulnerable plugin version with the feature enabled.
- Target account has a stale high-privilege role stored in user meta from earlier use.
- Any authenticated session; missing nonce/capability on the reset flow.
Exploitation (example)
```bash
@ -591,21 +551,6 @@ Detection checklist
- Modify roles via `add_role()` / `remove_role()` without `current_user_can()` and `wp_verify_nonce()` / `check_admin_referer()`.
- Authorize based on a plugin option array (e.g., `viewing_admin_as_role_are`) instead of the actors capabilities.
Hardening
- Enforce capability checks on every state-changing branch (e.g., `current_user_can('manage_options')` or stricter).
- Require nonces for all role/permission mutations and verify them: `check_admin_referer()` / `wp_verify_nonce()`.
- Never trust request-supplied usernames; resolve the target user server-side based on the authenticated actor and explicit policy.
- Invalidate “original roles” state on profile/role updates to avoid stale high-privilege restoration:
```php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
```
- Consider storing minimal state and using time-limited, capability-guarded tokens for temporary role switches.
---
### Unauthenticated privilege escalation via cookietrusted user switching on public init (Service Finder “sf-booking”)