مبحث یکم : مقدمه و تاریخچه
مبحث دوم: مراحل نفوذ کردن / جلوگیری از نفوذ
مبحث سوم: حملات شبکه ای
مبحث چهارم - کار عملی
مبحث پنجم - DHCP
مبحث ششم - وب و حملات مطرح در آن
مبحث هفتم - حملات DoS
مبحث هشتم - سیستم عامل
مبحث نهم - مهندسی اجتماعی
مبحث دهم - Vulnerability (آسیب پذیری)

ASLR در لینوکس

چه اتفاقی در زمان سرریز بافر رخ می داد (شکل 1)؟

شکل 1

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

چند مدل shell code داریم؟

Port binding، reverse shell، command execute و …

command execute: به واسطه این shell code یک دستور خاص روی سیستم هدف انجام می شود.

Shell codeهای port binding، یک پورت را روی سیستم هدف باز می کنند و می توان به آن پورت وصل شد و از سیستم sell گرفت (یعنی پورتی را باز می کند و یک Application روی آن پورت listen می کند)

Reverse shell: روی سیستم نفوذگر یک پورت گر یک پورت listen می کند از سیستم هدف ارتباط برقرار می‌شود. بدین نحو فایروال‌هایی که جلوی ترافیک ورودی (incoming) را می گیرند، bypass می شوند.

روال قرارگیری shell code (شکل2): قرار دادن shell code در بافر و پر کردن ادامه حافظه با آدرس shell code. آدرس shell code روی EIP می نشیند و به ابتدای shell code اشاره می کند. Extended Instruction Pointer (EIP) رجیستری در CPU است که همیشه به دستوری که باید اجرا شود، اشاره می‌کند.

شکل 2

      یکی از راه‌های جلوگیری از سرریز بافر کنترل سایز ورودی است.

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

وجود فایروال در مسیر سیستمی با شرایط بالا کمک می کند که حمله کننده نتواند به هر پورت دسترسی داشته باشد و آن پورت را باز کند (روی سیستم هدف و listen کند) البته ممکن است reverse shell در این سناریو جواب دهد.

برخی از shell codeها مثل reverse shell فضای زیادی از حافظه را اشغال می کنند و برخی دیگر مثل command execute فضایی کمتری. سئوال: کوچک کردن فضای بافر می تواند به جلوگیری از تزریق shell code کمک کند؟ بله، آزادی عمل را از حمله کننده می گیرد (مثلاً می توان مقدار بافر را در صورت امکان از کوچکترین سایز shell codeها کمتر گرفت) با این کار باز هم overflow رخ می دهد اما برنامه crash می کند (و اجازه اجرای shell code داده نمی شود). پس اندازه بافرها را به مقدار نیاز (کوچک تا حد امکان) قرار دهید.

البته روش‌های حمله ای وجود دارند که نیاز به shell code  ندارند (روش return into libc).

فرض کنید که یک برنامه نوشته ایم که صرفاً یک مقداری را با scanf از کاربر می گیرد و آن را با printf نمایش می‌دهد. برای استفاده از این توابع نیاز به include کردن یک کتابخانه داریم (کتابخانه stdio.h). با این include کردن به سیستم عامل گفته می شود فایل مورد نظر را برای استفاده در این برنامه در اختیار برنامه قرار دهد. سیستم عامل کل فایل را به برنامه ما می چسباند. حال این مسئله را می توان بسط داد به dllها، shell libraryها، static library و غیره. نفوذگرها زمانی که دیدند  جلوی shell code گرفته شد، از همین توابعی که به برنامه اضافه می شود استفاده کردند. یعنی با فرض این که فقط چند بایت از فضای بافر را در اختیار داشته باشیم، به جای قرار دادن shell codeها (که نیاز به فضای زیادی دارد) آدرس مثلاً تابع halt را قرار می دهیم. این کار با این فرض انجام می شود که برنامه نوشته شده برنامه کاملی است. حتماً از کتابخانه stdio هم استفاده کرده و در این کتابخانه هم یک تابع به نام halt است (یا تابع exit). کتابخانه ای که در C استفاده می شود در لینوکس libc، glibc هستند (به همین علت نام روش  return to libcقرار داده شده است). حتی بحث های دیگری مثل زنجیره returnها نیز مطرح شده است ( =Return Oriented Programming :ROP chainبرنامه نویسی مبتنی بر Return). کاری که در این روش انجام می شود این است: وقتی که مثلاً آدرس تابع half را قرار دادند، از آن جایی که آن تابع هم وقتی می خواهد تمام شود یک مقداری را از stack، pop می کنند، در آن جا نیز آدرس یک تابع دیگر را قرار دادند و همین طور الی آخر. بدین ترتیب با زنجیره ای از فراخوانی ها عملیاتی را انجام می دهند که در نهایت می تواند منجر به shell گرفتن شود.

از جمله کارهای دیگری اثر حمله سرریز بافر کم شود و یا این که اصلاً حمله ای انجام نشود عبارت اند از: قوی کردن مدیریت حافظه (Memory Management)، Set کردن permissionها، محافظت از رجیستر IP است. البته یکی از کارهای دیگر که انجام شد این بود که permission اجرای shell code را از برنامه بگیریم، بحثی مطرح شد به نام exec shield  (حافظه های exec)؛ و یا راه حل DEP (Data Execution Prevention): این روش قسمت هایی از حافظه را به عنوان Read Only قرار می دهد و اجازه اجرای کدهای آن قسمت از حافظه را نمی دهد که این کار را با Memory Management انجام می گیرد. یعنی فضاهای بافر از فضای کد جدا می شوند. پس لزومی ندارد که در بافر یک کد اجرایی باشد. سازندگان پردازنده ها هم در این بحث سهیم شدند و تکنولوژی هایی را ارائه کردند تا سیستم عامل از آن ها استفاده بکند مثل تکنولوژی NX که توسط اینتل (Intel) ارائه شد و یا تکنولوژی XD. تکنیک دیگر SSP (stack smashing protector) است که یک روش حفاظت از خراب شدن stack است. کار این روش این است که قبل از قرار گرفتن  IP(EIP) در شکل 1، یک مقدار دیگر تحت عنوان canary (قناری) قبل از IP قرار می گیرد (شکل 3) (به این روش Canary-Based Protection می گویند).

شکل 3

این مقدار canary یک مقدار ثابت و مشخصی است و هر زمان در تابع قرار باشد عمل return انجام گیرد قبل از آن، مقدار قناری بررسی می گردد. اگر این مقدار عوض شده بود یک پیغام خطا داده شود و دیگر return انجام نمی گیرد (برنامه همین جا متوقف می شود). در نظر دارید که وقتی over flow می خواهد انجام گیرد، این مقدار قناری را خراب می کند تا به IP برسد. علت نامگذاری این روش هم بر می گردد به این که در زمان قدیم کسانی که در معدن کار می کردند یک قناری با خود به معدن می بردند. زمانی که گازی یا … نشت می کرد چون قناری به این موضوع حساس است و از خود واکنش نشان می دهد می فهمیدند که اتفاقی افتاده است. این مقدار قناری به صورت غیرقابل پیش بینی (با هر بار اجرا) set می شود و یک نسخه از آن هم در جایی دیگر (برای مقایسه مقدار اصلی) ذخیره می شود (مثلاً در رجیسترgs در cpu)

تکنیک دیگر، امن کردن توابع پر استفاده بوده است (مثلاً امن کردن تابع strcpy() در زبان C که عمل کپی یک رشته از داخل یک متغیر به متغیر دیگر را انجام می دهد و یا ارائه کتابخانه هایی امن مثل libsafe).

البته برای برخی از این تکنیک ها نیز تکنیک های bypass توسط حمله کنندگان ارائه شده است.

مثلاً روش bypass برایexec shield  همان return to libc است. روش return in to libc بدین صورت است که آدرس توابع را به جای کد قرار می دهیم. حالا این مسئله را می توانیم بسط دهیم به Application های خاص منظوره. مثلاً برنامه بانکی در حال اجرا است و در حال واریز به یک شماره حساب است شما return address را به ابتدای تابع واریز مبلغ پاس می دهید. اتفاقی که می افتد این است که دائماً مبلغ واریز می شود.

آخرین تکنیکی هم که بررسی می کنیم روشی است تحت عنوان ASLR.

(Address Space Layout Randomization) ASLR = تصادفی سازی فضای آدرس برنامه ها. نفوذگر قصد کنترل return address را دارد و می خواهد آن را به مکان مشخصی set کند یا به ابتدای sell code یا به اجرای یک تابع (در return to libc). ASLR در هر بار اجرا، کامپایل، reset شدن سیستم و … آدرس ها را عوض می کند (معمولاً آدرس کتابخانه ها، heap، stack). با این کار دیگر حمله کننده نمی تواند یک نسخه از برنامه آسیب پذیر را روی سیستم خود نصب و تست کند و آدرس را پیدا کند و برای همه کامپیوترها استفاده کند چرا که آدرس­ها هر بار در حال عوض شدن هستند. برای این تکنیک نیز روش bypass ارائه شده است. ASLR یک قابلیت است که باید فعال شود.

معرفی وب سایت:

www.admantium.persiangig.com/documents

www.flazx.us

www.chmpdf.com

اسکرول به بالا