بررسی مکانیزم‌های امنیتی لینوکس (بخش دوم)

محافظت از کد

هفته گذشته، به‌‌معرفی مکانیزم‌های مختلف لینوکس در مقابل حمله‌های امنیتی پرداختیم. در این شماره، در ادامه روند بررسی مکانیزم‌ها، سراغ دو بخش دیگر خواهیم رفت: FORTIFY_SOURCE
کد خبر: ۳۵۷۷۹۶

این روش با جلوگیری از سرریز بافر به‌ وسیله جایگزینی توابع ناایمن با توابع همانند آنها ولی امن، امنیت را تامین می‌کند. همچنین اگر سرریزی رخ‌داد، این مکانیزم اجرای پروسس را متوقف می‌کند. گفتنی است اندازه بافر هنگام کامپایل یا اجرا تشخیص داده نمی‌شود و برخی از نفوذها ممکن است توسط این مکانیزم شناخته نشوند. همچنین این مکانیزم برای حفره‌های امنیتی رشته‌ها نیز تدابیری اندیشیده است.

بهتر است اشاره شود که اسکریپت می‌تواند برای تملک FORTIFY_SOURCE از طریق یک سمبل اقدام کند و متوجه شود که این باینری مسلح به مکانیزم دفاعی است یا نه؟ یعنی به‌صورت فرضی، یک باینری می‌تواند از هیچ‌یک از توابع FORTIFY استفاده نکند یا شرایطی رخ دهد که این مکانیزم فعال نشود (سایز بافر تا پیش از اجرا مشخص نباشد) که نتیجه مثبت، نادرست از آب در خواهد آمد.

همچنین اگر اندازه تمام بافرها پیش از کامپایل مشخص باشد، نیازی به استفاده توابع FORTIFY‌ وجود ندارد و از این‌رو باز هم نتیجه غلط، نادرست می‌شود. برای این که این مکانیزم فعال شود، فایل باینری باید پیش از کامپایل پرچم بهینه‌سازی را با مقدار حداقل2 پر کند. این کار را می‌توان با فرستادن گزینه O2– به gcc هنگام کامپایل انجام داد.

همان‌طور که از نمودار بالا می‌توان دریافت، تمام توزیع‌های مقایسه شده به‌جز دبیان از این سیستم محافظتی خوب استفاده می‌کنند و حدود 80 درصد از باینری‌ها با این مکانیزم محافظت شده‌اند. جنتو به 90درصد رسیده است و این نشان می‌دهد که دیگر توزیع‌ها می‌توانند برای چند باینری دیگر این سیستم را فعال کنند. با این وجود باید اشاره کرد که جنتو به‌صورت پیش‌فرض پروسس‌های کمتری را اجرا می‌کند. در این مقایسه، دبیان تنها برای دو پروسه این مکانیزم را فعال کرده است (3درصد) و هر دوی آنها متعلق به بسته Kerneloops بوده‌اند.

اجرایی‌های مستقل از مکان (PIE)

توانمندی پیش‌بینی آدرس‌های حافظه یک پروسه و بخش‌های آن کمک بزرگی به مهاجم است تا به سیستم نفوذ کند. هرچند در سال‌های اخیر تصادفی‌کردن آدرس‌های حافظه در سیستم‌های‌عامل به‌کار رفته، اما بیشتر باینری‌ها هنوز به‌ شیوه قدیمی در لینوکس بارگذاری می‌شوند، مگر این‌ که به‌صورت فایل اجرایی مستقل از مکان کامپایل شوند.

کامپایل کردن باینری به‌عنوان مستقل از مکان به سیستم‌عامل اجازه می‌دهد تمام بخش‌های یک پروسس را هنگام اجرا در آدرس‌های تصادفی قرار دهد. این اقدام باعث می‌شود نفوذ به سیستم بسیار دشوار باشد و این تصادفی قرار دادن پروسس‌ها، به یک آنتروپی منجر شود؛ یک سیستم 64 بیتی می‌تواند سیستم تصادفی بهتری از یک سیستم 32 بیتی داشته باشد، چراکه رنج آدرس‌دهی آن به ‌مراتب وسیع‌تر از سیستم‌های 32 بیتی است.

تمام هسته‌های مدرن قابلیت تصادفی‌سازی بخش‌هایی از حافظه فضای آدرس یک پروسه را دارند حتی اگر این پروسه به‌صورت مستقل از مکان کامپایل نشده باشد. این موضوع از طریق تنظیمات randomise_va_space در سیستم فایل proc کنترل می‌شود. وقتی این مقدار 2 باشد، لینوکس درخواست‌های پشته، هیپ و (mmap)را به‌صورت تصادفی قرار می‌دهد. وقتی به 1 تغییر پیدا می‌کند، فقط فضای پشته به‌صورت تصادفی چیده ‌خواهد شد.

همان‌طور که پیش از این اشاره شد، بخش‌هایی از حافظه یک پروسس می‌تواند وجود داشته باشد که به یک مکان خاص حافظه اشاره می‌کند، هرچند کد یک پروسس به‌صورت مستقل از مکان کامپایل شده باشد. مهاجم در این حالت باید یا از طریق حدس، یا از طریق Bruteforce این مکان از حافظه را حدس بزند.

البته بهتر است اشاره شود که کدهای مستقل از مکان در معماری x86 مشکل بازدهی دارند و بین 1 تا 5 درصد نسبت به کدهای غیرهمنوع کندتر عمل می‌کنند. برخی از نرم‌افزارها خصوصا اگر به‌ زبان ماشین نوشته شده باشند، نمی‌توانند به‌صورت مستقل از مکان کامپایل شوند.

همان‌طور که در نمودار بالا می‌توان مشاهده کرد، بیشتر توزیع‌های مقایسه شده از این مکانیزم در وسعت بالا استفاده نمی‌کنند. مقادیر از 8 درصد (دبیان) تا اوپن‌سوسه (21درصد) متغیر است ولی جنتو به 100درصد رسیده است. همچنین بهتر است اشاره شود که توزیع‌ها از این قابلیت تنها برای پروسه‌‌های فوق حساس، از جمله سرویس‌های تحت شبکه SSH استفاده می‌کنند. با این وجود، صرف نظر از جنتو، تنها اوبونتو مکانیزم مستقل از مکان را برای فایرفاکس فعال کرده است.

چراکه بیشتر حملات از طریق مرورگر و حفره‌های موجود در آنها انجام می‌شود، از این رو بهتر است این نوع پروسس‌ها در مقابل حملات مقاوم‌تر شوند. تجربه نشان داده است کاربر به سیستم‌های امنیتی پایه بسنده می‌کند و تنظیماتی را که به‌صورت پیش‌فرض توسط تولیدکننده فعال نشده، فعال نخواهد کرد. از این‌رو بهتر است پروسس‌های غیرسیستمی اما مهم نیز در مکانیزم‌های امنیتی شریک شوند.

هرچند این مکانیزم‌های امنیتی هر کدام تاثیر به‌خصوصی در بهبود امنیت سیستم دارند، بسته به نوع دیدگاه یک توزیع، پیاده‌سازی‌های این مکانیزم‌ها با یکدیگر متفاوت است و گاهی برخی پروسس‌های حساس از جمله پروسس‌های مبتنی بر شبکه با مکانیزم‌های بیشتری کنترل شده‌اند و برخی چون مرورگرهای وب خیلی امن نیستند.

به‌نظر می‌رسد هیچ گلوله سیمینی در سینه هیچ توزیع لینوکسی فرو نخواهد رفت. توزیع‌های مختلف مکانیزم‌های مختلف امنیتی دارند و به‌نظر می‌رسد برنده این مقایسه مشخص نیست.

هرچند پروژه Gentoo Hardened، بالاترین نرخ استفاده از مکانیزم‌های امنیتی فضای حافظه سمت کاربر را دارد و برای بهترین نتیجه امنیتی باید کمی دست‌ها را خاکی کرد و بهترین نتیجه را از تنظیمات گرفت.

از مسائل امنیتی سمت کاربر گفتیم اما بدون تنظیمات اضافه در سمت هسته سیستم، بیشتر مکانیزم‌هایی که شرح دادیم نمی‌توانند به‌طور کامل فعال شوند، از این‌رو بهتر است به بخشی از ویژگی‌های هسته بپردازیم که تاثیر مستقیمی روی امنیت باینری‌های در حال اجرا دارند.

جهت اختصار، برخی از فریم‌ورک‌های امنیتی از جمله SELinux، Grsecurty RBAC، AppArmor و مانند آنها در این مقاله گنجانیده نشده‌‌اند.

بیشتر قابلیت‌های هسته‌ای که در این بخش شرح داده می‌شوند، به سیستم‌های حفاظتی فضای سمت کاربر کمک می‌کنند. هرچند برخی از آنها مستقیما روی امنیت خود هسته تاثیر دارند. امنیت هسته بسیار مساله مهمی است و حمله کننده می‌تواند کد خود را در فضای هسته اجرا کند. این مساله نشان می‌دهد که باید امنیت هسته را فعال کرد.

هسته لینوکس توسعه سریعی دارد و به‌طور مداوم قابلیت‌های جدیدی به آن اضافه می‌شود و همچنین تطابق آن با دستگاه‌های جدید روز به‌روز بیشتر می‌شود.

از این‌رو باید اشاره کرد که تاثیر مستقیم و غیرمستقیم این مسائل در امنیت هسته لینوکس انکارناپذیر است. همچنین نامعقول نیست که فعال کردن قابلیت‌های امنیتی هسته منجر به کند شدن سیستم و هسته شود.

آزمون

در این آزمون، خروجی‌ها از تنظیمات زیر گرفته شده و ابزارهای مورد استفاده به‌صورت زیر هستند:

- 'mmap_min_addr' (/proc/sys/vm/mmap_min_addr)

- 'randomize_va_space' (/proc/sys/kernel/randomize_va_space)

- paxtest-0.9.9.tgz

گزینه اول برای تنظیم حداقل تعداد آدرس‌های مجازی است که می‌تواند در فضای کاربر تعریف شود.

این دستور مشکلات امنیتی زیادی دارد؛ مثلا اگر مهاجم بتواند یک پوینتر NULL را فراخوانی کند، به‌راحتی می‌تواند به هسته آسیب بزند. اگر صفحه‌ای در آدرس 0 قرار داشته باشد و با داده دلخواه پرشود، در این صورت تمام حافظه در اختیار مهاجم قرار می‌گیرد.

استفاده از این تنظیمات هسته و تغییر آن به مقدار امن‌تری، مثلا حداقل 64 کیلوبایت می‌تواند از نفوذها بکاهد.

دومین تنظیم مشخص می‌کند که بخش‌های حافظه‌ای یک پروسس هنگام اجرا آدرس‌های تصادفی دریافت می‌کنند. دومین تنظیم اگر به مقدار 0 تغییر کند، در این صورت عملیات تصادفی‌سازی به‌طور کامل غیرفعال می‌شود. اگر 1 تنظیم شود، آدرس‌های پایه در پشته و همچنین صفحه‌های VDSO و درخواست‌های mmap تصادفی‌ساز می‌شوند.

این یعنی کتابخانه‌های اشتراکی در آدرس‌های کاملا تصادفی بارگذاری شده و همانند باینری‌های مستقل از زمان، فراخوانی می‌شوند.

اگر این مقدار به 2 تغییر پیدا کند، به‌علاوه تمام حفاظت‌های پیشتر گفته شده، آدرس‌های پایه در حافظه هیپ نیز تصادفی‌سازی می‌شوند. البته توزیع‌هایی که بسته Pax را برای هسته خود قرار داده باشند، چه در حالت 1 و چه در حالت2، این قابلیت را برای آدرس‌های پایه حافظه هیپ فعال کرده‌اند.

محمدرضا قربانی

newsQrCode
ارسال نظرات در انتظار بررسی: ۰ انتشار یافته: ۰

نیازمندی ها