مختصری درباره ی گذشته ی LSMها
در کرنل نسخه 5.4 هشت LSM وجود دارد - SELinux، SMACK، AppArmor، TOMOYO، Yama، LoadPin، SafeSetID، و .Lockdown همچنین LSMهایی مانند SARA و KRSI در دست توسعه هستند که ممکن است به زودی جای خود را در منابع هسته در کنار سایرین بگیرند. دلیل اینکه چرا چنین تنوعی برای LSM وجود دارد، این است که برخی یک مساله ی رایج نوعی را به روش های منحصر به فرد حل می کنند در حالی که برخی دیگر به مسائل خاص می پردازند. تنها آگاهی از این تفاوت ها می تواند درک ما را از ویژگی ها و چالش های امنیتی در سیستم های لینوکس افزایش دهد.
LSMها چیستند؟
یک LSM کدی است که مستقیماً در کرنل لینوکس کامپایل شده است و با استفاده از فریم ورک LSM، می تواند دسترسی یک فرآیند به اشیاء مهم کرنل (Kernel Objects) را رد کند. انواع اشیا محافظت شده شامل فایل ها، inodes، ساختارهای وظیفه (Task)، اعتبارنامه ها (Credentials) و اشیاء ارتباط بین پردازشی (Interprocess) می باشد. دستکاری این اشیاء نشان دهنده ی روش اصلی تعامل فرآیندها با محیط خود است و با مشخص کردن دقیق تعاملات مجاز، یک مدیر امنیتی می تواند سوء استفاده ی مهاجم از نقص موجود در یک برنامه را برای حمله به مناطق دیگر سیستم دشوارتر کند.
اولین و مسلماً رایج ترین مورد استفاده برای چارچوب LSM، اجرای سیاست های کنترل دسترسی اجباری, MAC(Mandatory Access Control) است. جای تعجب نیست که چندین رویکرد در مورد نحوه ی بهترین پیاده سازی MAC ها در هسته وجود دارد. در سال 2001، پیتر لوسکوکو از آژانس امنیت ملی یکی از اولین پیاده سازی ها را در اجالس کرنل لینوکس 2.5 ارائه کرد. جاناتان کوربت از اخبار هفتگی لینوکس پس از آن خاطرنشان کرد:
"شاید جالب ترین چیزی که از این بحث به دست آمد، مشاهده این بود که تعدادی از پروژه های مرتبط با امنیت کار مشابهی را انجام می دهند. همه دوست دارند روزی نتیجه ی کار را در هسته ی استاندارد ببینند. با این حال، در حال حاضر بسیار سخت است که بدانیم یک مکانیزم استاندارد لینوکس با امنیت بالا واقعاً چه شکلی باید باشد. بنابراین، توسعه دهندگان واقعاً دوست دارند پروژه های امنیتی را با هم ببینند و مجموعه ای از رابط های استاندارد را تعریف کنند که به همه ی آن ها اجازه می دهد به هسته متصل شوند، به طوری که کاربران بتوانند با بیش از یکی از آن ها آزمایش کنند. این پروژه ی آسانی به نظر نمی رسد، انتظار نداشته باشید که به این زودی آن را ببینید."
(Jonathan Corbet, Linux Weekly News)
چند سال بعد "مجموعه رابط های استاندارد" (Set of Standard Interfaces) به فریم ورک LSM تبدیل شد. از نسخه 5.4 تا کنون، فریم ورک شامل 224 نقطه هوک در سراسر کرنل، یک API برای ثبت توابع در این نقاط هوک و یک API برای رزرو حافظه مرتبط با اشیاء محافظت شده ی کرنل برای استفاده توسط LSMها است. با انتشار کرنل 2.6 در پایان سال 2003، هر دو فریم ورک LSM و SELinux برای استفاده از فریم ورک به جای پچ شدن مستقیم کرنل اصلاح شد (ادغام شدند). در حالی که جزئیات پیاده سازی LSM در طول زمان تغییر می کند، هدف اصلی اجازه دادن به کنترل دقیق بر دسترسی به اشیاء مهم کرنل است.
فریم ورک LSM کنونی به کاربر اجازه می دهد تا چندین LSM را در کرنل کامپایل کند که می توانند به طور همزمان روی هم اِستَک و استفاده شوند. نمودار زیر یک جریان فراخوانی را برای ()open نشان می دهد که در آن سه LSM هوک های ثبت شده دارند:
1. یک فرآیند (Process) در فضای کاربر (user-space)، ()open را در مسیر فایل فراخوانی می کند.
2. فراخوانی سیستم (System Call) ارسال می شود و رشته مسیر برای به دست آوردن یک شی فایل کرنل استفاده می گردد. اگر پارامترها نادرست باشند، یک خطا برگردانده می شود.
3. مجوزهای فایل کنترل دسترسی اختیاری "عادی" بررسی می شود. آیا کاربر فعلی مجوز باز کردن فایل درخواستی را دارد؟ در غیر این صورت، سیستم کال خاتمه می یابد و یک خطا به کاربر برگردانده می شود.
4. اگر DAC ها راضی باشند، فریم ورک LSM هر یک از هوک های file_open را برای LSM های فعال فراخوانی می کند. سیستم کال خاتمه مییابد و اگر یک هسته ی LSM خطایی را برگرداند، یک خطا به کاربر برمی گردد.
5. در نهایت، اگر تمام بررسی های امنیتی انجام شود، فایل برای پردازش باز می شود و یک توصیف کننده فایل (file descriptor) جدید به فرآیند در فضای کاربر باز می گردد.
محل LMS در یک سیستم کال open
LSMهای اصلی، فرعی و انحصاری
با درک اولیه از چیستی LSM، می توانیم توجه خود را به آنچه که LSM های مختلف واقعا در کرنل انجام می دهند معطوف کنیم. برای شروع، اجازه دهید نگاهی به LSM" های اصلی" داشته باشیم. این LSMSها - SELinux، SMACK، AppArmor و TOMOYO - همگی پیاده سازی های MAC با خط مشی های قابل تنظیم هستند که از فضای کاربر بارگیری می شوند. آن ها مسائل مشابه را به روش های منحصر به فرد حل می کنند.
LSMهای اصلی قدیمی از نظر تاریخی نمی توانستند همزمان بارگیری شوند. زیرا طراحان اصلی فریم ورک LSM اجازه فعال کردن تنها یک LSM را می دادند. همه ی LSMهای اصلی فرض می کردند که به نشانگرهای زمینه ی امنیتی (Security Context Pointers) و شناسه های امنیتی (Security Identifiers) تعبیه شده در اشیاء کرنل محافظت شده، دسترسی انحصاری دارند. بنابراین، تنها یک LSM اصلی می تواند در هر زمان مورد استفاده قرار گیرد، که همانطور که در شکل زیر مشاهده می شود میتواند به عنوان یک گزینه در زمان کامپایل کرنل پیکربندی شود و یا به عنوان یک پارامتر در خط فرمان کرنل ارسال گردد.
فهرست پیکربندی کرنل برای انتخاب LSM اصلی پیش فرض
در ادامه ی روند، فریم ورک LSM برای حذف این تمایز بین LSMهای "اصلی" و "فرعی" تغییر و تحول می یابد. در حال حاضر روش ترجیحی برای تشخیص LSMها با پرچم LSM_FLAG_EXCLUSIVE است تا واضح تر شود که تمایز اصلی / فرعی واقعاً در مورد انحصار است. یک کاربر می تواند هر تعداد LSM را تا زمانی که فقط یکی از آن ها دارای مجموعه LSM_FLAG_EXCLUSIVE باشد را پیکربندی کند. در حال حاضر فقط SELinux، SMACK و AppArmor به عنوان انحصاری علامت گذاری شده اند، AppArmor هم به زودی به این مجموعه می پیوندد و سایرین نیز دنباله روی آن ها خواهند شد.
LSM های فرعی نه تنها چون به زمینه ی کمتری نیاز دارند برای استک شدن آسان تر هستند، بلکه اکثر سیاست های خود رامستقیماً در کد کدگذاری می کنند. LSM های فرعی به جای داشتن فایل های خط مشی که از فضای کاربر به عنوان بخشی از شروع سیستم بارگیری می شوند،معموالً فقط حاوی پرچم هایی برای فعال کردن/غیرفعال کردن گزینه ها هستند.
SELINUX (SECURITY ENHANCED LINUX) – امنیت پیشرفته ی لینوکس
SELinux ابتدا به عنوان بخشی از لینوکس 2.6 ادغام شد و پیاده سازی MAC پیشفرض در توزیع های لینوکس مبتنی بر RedHat است. به دلیل قدرتمند بودن و پیچیده بودنش معروف می باشد.
SELinux مبتنی بر ویژگی (attribute-based) است که به این معنی است که شناسه های امنیتی فایل ها در ویژگی های فایل توسعه یافته در سیستم فایل ذخیره می شوند. به عنوان مثال، می توانید از دستور ls -Z برای مشاهده ی زمینه ی امنیتی در /bin/bash استفاده کنید، که در مثال زیر system_u:object_r:shell_exec_t:s0 می باشد. چهار فیلد با دونقطه از هم جدا شده اند و معرف user:role:type:level هستند.
$ls -Z /bin/bash
-rwxr-xr-x. root root system_u:object_r:shell_exec _t:s0 /bin/bash
رایج ترین راه برای تعیین خط مشی ها در SELinux این است که مشخص کنید موارد مرتبط با SELinux (یا کاربران در این مورد) مجاز به انجام چه اقداماتی بر روی اشیاء برچسب شده با یک نوع خاص هستند. با نگاهی دوباره به خروجی ls بالا، مجوزهای کالسیک DAC نشان می دهند که همه ی کاربران در سیستم مجاز به خواندن و اجرای bash هستند، اما با SELinux، یک مدیر امنیتی می تواند در فایل های سیاست گذاری، مواردی که مجاز به اجرا یا خواندن فایل هایی از نوع shell_exec_t هستند را مشخص کند؛ معقول به نظر می رسد در صورتی که وب سرور در برابر حمله ی اجرای کد از راه دور آسیب پذیر باشد یک مهندس امنیتی نخواهد به وب سرور اجازه ی اجرای یک شِل (Shell) را بدهد.
یکی از عوارض جانبی استفاده ی SELinux از ویژگی های توسعه یافته (extended attributes) این است که SELinux برای محافظت از اشیاء در سیستم های فایل که از ویژگی های توسعه یافته پشتیبانی نمی کنند - مانند نصب NFS قبل از NFSv4 - مفید نیست.
(SIMPLIFIED MANDATORY ACCESS CONTROL) - SMACK کنترل دسترسی اجباری ساده شده
کنترل دسترسی اجباری ساده شده (SMACK)، مانند SELinux، یک پیاده سازی MAC مبتنی بر ویژگی است و دومین توسعه دهندگان LSM بود که در هسته ی لینوکس ادغام شد (به عنوان بخشی از نسخه 2.6.24). برخالف SELinux ،SMACK برای سیستم های تعبیه شده (Embedded Systems) و ساده تر برای مدیریت طراحی شده است. SMACK پیاده سازی پیش فرض MAC در لینوکس Automotive Grade و Tizen است.
APPARMORAppArmor یکی دیگر از پیاده سازی های MAC است که در ابتدا توسط Immunix توسعه داده شد و به عنوان بخشی از نسخه 2.6.36 در هسته ادغام شد. AppArmor اولین پیاده سازی MAC در سیستم های مبتنی بر دبیان است.
بارزترین تفاوت AppArmor و SELinux، علاوه بر کاهش ابزار و پیچیدگی، این است که مبتنی بر ویژگی نبوده بلکه مبتنی بر مسیر (path-based) است.
پیاده سازیهای مبتنی بر مسیر دارای مزایا و معایبی هستند. از جنبه ی مثبت، سیاست های مبتنی بر مسیرها می توانند از فایل ها در هر سیستم فایلی محافظت کنند زیرا ویژگی های توسعه یافته (Extended Attributes) برای ذخیره ی اطلاعات زمینه ی امنیتی (Security Context Information) مورد نیاز نیست. همچنین می توان قوانینی را برای فایل هایی که ممکن است هنوز وجود نداشته باشند تعیین کرد زیرا مسیر را می توان در پروفایل بدون نیاز به برچسب گذاری یک فایل یا دایرکتوری واقعی ذخیره کرد. بیشترین موارد منفی ذکر شده این است که به دلیل توانایی ایجاد پیوندهای متقن (Hard Links)، ممکن است چندین مسیر وجود داشته باشد که به یک فایل فیزیکی اشاره دارد. سیاست امنیتی برای یک فایل نوعی بسته به مسیری که برای دسترسی به آن استفاده می شود، می تواند متفاوت باشد که این ممکن است حفره های امنیتی غیرمنتظره ای را باز کند.
TOMOYO
TOMOYO، مانند AppArmor، یکی دیگر از پیاده سازیهای MAC مبتنی بر مسیر است و ابتدا به عنوان بخشی از Linux 2.6.30 ادغام شد. TOMOYO برای محافظت از سیستم های تعبیه شده با اجازه دادن به مدیران امنیتی برای ضبط تمام تعاملات فرآیندِ (Process Interactions) حالت کاربر در طول آزمایش طراحی شده است، که سپس می تواند برای ایجاد سیاست هایی استفاده شود که تعاملات را فقط به مواردی که در طول توسعه / آزمایش مشاهده می شوند محدود نماید. هنگامی که سیستم های محافظت شده با TOMOYO در دست کاربران غیرقابل اعتماد یا در محیط های متخاصم قرار می گیرند، فرآیندهای حالت کاربر باید تنها به انجام اقدامات مشاهده شده قبلی محدود شود و ایجاد خط مشی را ساده تر کند.
LOADPINLoadPin که در لینوکس 4.7 ادغام شده است، یک LSM "فرعی" است که تضمین می کند همه ی فایل های بارگذاری شده با کرنل (ماژول ها، سیستم عامل و غیره) از یک سیستم فایل منشا می گیرند، با این انتظار که چنین سیستم فایلی توسط یک دستگاه فقط خواندنی پشتیبانی می شود. . این به منظور ساده سازی سیستم های تعبیه شده است که به هیچ یک از زیرساخت های علامت زدن ماژول کرنل (Kernel Module Signing) - بررسی اینکه آیا سیستم برای بوت شدن از دستگاه های فقط خواندنی پیکربندی شده است یا خیر - نیاز ندارند.
"امنیتی" که به سادگی قابل استفاده شدن است احتمالا بیشتر مورد استقبال قرار می گیرد؛ LoadPin می تواند فرآیند محافظت از کرنل در برابر ماژول های مخرب را برای انواع خاصی از سیستم های تعبیه شده ساده کند.
YAMAYama که در لینوکس 3.4 ادغام شده است، یک LSM می باشد که برای جمع آوری محدودیت های امنیتی DAC در سطح سیستم طراحی شده است که توسط کرنل اصلی مدیریت نمی شوند. در حال حاضر از کاهش حوزه ی (Scope) سیستم کالِ ()ptrace پشتیبانی می کند تا حمله ی موفقیت آمیز به یکی از فرآیندهای در حال اجرا کاربر نتواند از ptrace برای استخراج اطلاعات حساس از سایر فرآیندهایی که از جانب همان کاربر اجرا می شوند استفاده کند.
SAFESETIDSafeSetID، ادغام شده در لینوکس 5.1، یک LSM است که برای محدود کردن انتقال UID/GID از یک UID/GID معین به مواردی که توسط یک لیست سفید در سراسر سیستم تایید شده اند استفاده می شود.
شرح مورد استفاده SafeSetID در منابع کرنل نیازی به بازنویسی ندارد:
"این می تواند برای اجازه دادن به یک برنامه ی غیر ریشه ای (Non-root Program) برای انتقال به دیگر uid های نامعتبر بدون قابلیت های کامل CAP_SETUID استفاده شود. برنامه ی غیر روت برای انجام هر نوع انتقال همچنان به CAP_SETUID نیاز دارد، اما محدودیت های اضافی اعمال شده توسط این LSM به این معنی است که این نسخه "ایمن تر" از CAP_SETUID است زیرا برنامه ی غیر روت نمی تواند از مزیت CAP_SETUID برای انجام کارهای تأیید نشده (به عنوان مثال setuid به uid 0 یا ایجاد/وارد فضای نام کاربری جدید) استفاده کند. هدف سطح بالاتر، اجازه دادن به سندباکس مبتنی بر uid از سرویس های سیستمی بدون نیاز به ارائه CAP_SETUID در همه جا است تا برنامه های غیر روت بتوانند به uidهای با امتیاز کمتر (Even-lesser-privileged) کاهش یابند. این امر به ویژه زمانی مرتبط است که یک دیمون غیر ریشه (Non-root Daemon) - یک فرآیند پس زمینه که به درخواست های خدماتی مانند اسپول کردن چاپ و انتقال فایل رسیدگی می کند و در صورت عدم نیاز غیرفعال است - در سیستم باید اجازه داشته باشد که فرآیندهای دیگر را به عنوان uid های مختلف ایجاد کند، اما اینکه که به دیمون یک CAP_SETUID معادل ریشه ای داده شود اساسا نامطلوب است."
Documentation/admin-guide/LSM/SafeSetID.rst
LOCKDOW LSM
Lockdown که در لینوکس 5.4 ادغام شده است یک LSM می باشد که یک ویژگی «قفل کردن» را برای کرنل پیاده سازی می کند. وقتی lockdown فعال است، می توان از یک پارامتر خط فرمان کرنل جهت قفل کردن کرنل برای یکپارچگی (Integrity) یا محرمانگی (Confidentiality) استفاده کرد. وقتی lockdown روی یکپارچگی تنظیم می شود، ویژگی هایی که به فضای کاربران اجازه می دهند کرنل را تغییر دهد غیرفعال می شوند. این ویژگی ها عبارتند از: بارگذاری ماژول بدون عالمت (Unsigned Module Loading)، دسترسی بهdev/{mem,kmem,port}/، دسترسی به kexec ،/dev/efi_test، تصاویر بدون علامت، Hibernation، دسترسی مستقیم PCI، دسترسی به پورت IO خام، دسترسی MSR خام، تغییر جداول ACPI، ذخیره سازی مستقیم PCMCIA CIS، پیکربندی مجدد پورت سریالIO، پارامترهای ماژول ناامن، mmio ناامن و دسترسی اشکال زدایی (Debugfs). وقتی lockdown روی محرمانه بودن تنظیم می شود، علاوه بر اینکه تمام حفاظت های یکپارچگی فعال می شوند، ویژگی هایی که به کاربر اجازه می دهد تا اطلاعات محرمانه ی بالقوه از یک کرنل در حال اجرا - مانند دسترسی /proc/kcore، استفاده از kprobes، استفاده از bpf برای خواندن RAM کرنل، استفاده ی ناایمن از perf و استفاده از tracefs - را استخراج کند غیرفعال می گردد.
ویژگی قفل کردن را می توان از طریق فایل های خط مشی SELinux، AppArmor، SMACK یا TOMOYO پیاده سازی کرد، اما پیاده سازی آن در یک LSM پشته پذیر جداگانه با یک خطم شی استاتیک به این معنی است که می توان آن را بدون توجه به پیاده سازی MAC خاص در حال استفاده، در سراسر توزیع ها استفاده نمود.
نتیجه گیری
LSM ها برای جلوگیری از حمله به یک فرآیند طراحی نشده اند. شیوه های کدنویسی خوب، مدیریت پیکربندی و زبان های ایمن حافظه، ابزارهایی برای آن هستند. با این حال، حفاظت های ارائه شده توسط LSM ها زمانی که یک مهاجم از نقص های یکی از برنامه های در حال اجرا سوء استفاده می کند، به محافظت از سیستم شما در برابر هک شدن کمک خواهد کرد. آن ها می توانند یک لایه ی مهم در هر استراتژی دفاعی عمیق در سیستم های لینوکس باشند، و درک اینکه چه محافظت هایی ارائه می کنند، به درک بیشتر ما از سیستم هایی که نیاز به محافظت دارند و نحوه اجرای آن محافظت ها منجر خواهد شد.