حملات Buffer Overflow

Buffer-overflow-attack-rnpg
تاریخ انتشار : 2020/08/10 | نویسنده : Mr-M4HDI

حملات Buffer Overflow

Buffer overflow چیست

Buffer overflow یک شکاف امنیتی می باشد و زمانی رخ می دهد که داده های اضافی بر روی بلوک حافظه

یا بافر نوشته و سپس بافر به این داده ها اختصاص داده شود و این داده ها بیشتر از مقداری که یک بافر

می تواند در خود نگه دارد، باشد. Exploit نمودن Buffer overflow به یک هکر اجازه می دهد، اطلاعات را از

بین ببرد، اپلیکیشن را از دسترس خارج و یا کد مخرب خود را بر روی سیستم هدف اجرا نماید؛ همچنین

می تواند بخشی از آدرس فضای فرایند هدف (process address space) را تغییر دهد.

این قابلیت ممکن است برای اهداف متنوعی استفاده شوند:

* کنترل اجرای فرایند (Control the process execution)

* اختلال در فرایند (Crash the process)

* تغییر متغیر های داخلی (Internal variables)

فرض کنید کامپیوتری یک بافر 40 بایتی برای ذخیره 10 رشته (4 بایت در هر رشته) اختصاص داده است.

حال یک هکر 11 رشته (در مجموع 44 بایت) را به عنوان ورودی ارسال می کند. همانطور که در تصویر زیر

نشان داده شده است. ورودی هکر بیش تر از مقداری که بافر به داده های ورودی اختصاص داده است،

می باشد.

what-is-buffer-overflow

 

دلایل بروز آسیب پذیری Buffer overflow 

بخشی از این مشکل امنیتی به دلیل وجود راه های متنوع برای بهره برداری از آسیب پذیری Buffer overflow

بوده و بخش دیگر آن به دلیل پیچیدگی در جلوگیری از این آسیب پذیری می باشد.

کشف آسیب پذیری های Buffer overflow ساده نیست و حتی هنگامی که یکی از آنها یافت می شود، بهره

برداری از آن بسیار دشوار می باشد؛ با این وجود هکر ها توانسته اند Buffer overflow های مختلفی در

محصولات و نرم افزار های مختلف بیابند.

 

نحوه بهره برداری ازBuffer overflow

در حملات کلاسیک، هکر داده ها را به سمت برنامه ای ارسال می کند که دارای بافر پشته ای با حجم

محدود می باشد، در نتیجه داده ها بر روی پشته Call از جمله تابع pointer بازنویسی می شوند.

اکثر اوقات هدف هکر کنترل فرایند اجرای هدف می باشد؛ این امر با شناسایی تابع pointer در حافظه انجام

می شود که می تواند با استفاده از overflow به صورت مستقیم یا غیر مستقیم تغییر پیدا کند.

هنگامی که این pointer برای اجرای مستقیم برنامه از طریق دستور العمل های call و jump، توسط برنامه

استفاده شود، اجرای دستورالعمل های ارائه شده توسط هکر را در پی خواهد داشت، در نتیجه به هکر اجازه

می دهد تا فرایند را کنترل کند.

در بسیاری از موارد، pointer برای ارجاع به مکانی که هکر دستورالعمل های خود را قرار داده است، تغییر پیدا

می کند. با توجه به این که هکر ها معمولاً تمایل دارند بر روی سیستم هدف یک خط فرمان اجرا نمایند،

معمولاً دستور العمل های خود را به عنوان Shellcode در نظر می گیرند.

اگرچه این نوع آسیب پذیری هنوز در برخی از سیستم عامل ها و در برخی از اپلیکیشن های در حال توسعه

رایج است، انواع مختلف دیگری همچون Heap buffer overflow و Off-by-one error در این حوزه وجود دارد.

یک کلاس مشابه دیگری از این آسیب پذیری ها که می توان به اشاره نمود حمله Format string  می باشد.

 

تفاوت Stack و Heap

رایانه ها معمولاً به دو مدل تخصیص حافظه، متکی هستندکه به عنوان stack و heap شناخته می شوند و هر

دو در RAM رایانه ها وجود دارند. Stack به طور مرتب سازماندهی شده است و داده ها را در یک مدل، Last-In

و First-Out نگه داری می کند. به عبارت دیگر هر آنچه که آخر در پشته قرار داده خواهد شد، اولین موردی

می باشد که از پشته خارج می شود.

Heap یک pool نا منظم از حافظه اضافی می باشد که داده ها بدون هیچگونه ترتیب خاصی در آن ذخیره

می شوند. از آنجائیکه دسترسی به داده در Stack از Heap سریعتر است. پس به طور کلی از heap برای

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

 

Heap-vs-stack-rnpg

 

 

انواع مختلف حملات buffer overflow

تعدادی از حملات buffer overflow وجود دارد که با استفاده از استراتژی های متفاوت بخش های مختلفی از

کد را مورد هدف قرار می دهد. در ذیل تعدادی از این حملات شناخته شده نام برده شده است:

 

حمله Stack overflow

در مبحث نرم‌افزار، سرریز بافر پشته (Stack buffer overflow) وقتی اتفاق می‌افتد که یک برنامه، اطلاعاتی را

در آدرسی خارج از ساختمان داده مورد نظرش (معمولاً بافری با اندازه ثابت) که در پشته فراخوانی برنامه قرار

دارد، می‌نویسد. ظرفیت بافرهای با اندازه ثابت، از قبل و در زمان کامپایل تعیین شده‌است و در صورتی که

اطلاعاتی بیشتری در آن‌ها نوشته شود، سرریز خواهند شد و این‌گونه باگ‌ها را به وجود خواهند آورد. اگر این

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

این عمل خراب شدن و آسیب دیدن اطلاعات مجاور آن بافر در پشته است و در صورتی که این سرریز به‌طور

ناخواسته و بر اساس یک اشتباه به وجود آمده باشد، اغلب یا باعث می‌شود که برنامه متوقف شود یا اینکه

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

بافر است.

اگر برنامه‌ای که دچار سرریز بافر پشته شده، با امتیازها و دسترسی‌های بالایی اجرا شده باشد، یا اگر برنامه

اطلاعاتی را از میزبان‌های شبکه غیرقابل اطمینان دریافت کند (همانند یک وب سرور)، این باگ می‌تواند یک

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

اطمینان پر شود، آن کاربر می‌تواند کدهایی با قابلیت اجرا شدن را در پشته برنامه تزریق کرده و سپس کنترل

برنامه را در دست بگیرد. این نوع حمله، یکی از قدیمی‌ترین و قابل اتکاترین حملاتی است که مهاجمین و

خرابکاران از آن برای بدست آوردن دسترسی غیر مجاز به رایانه استفاده می‌کنند. روش‌هایی برای مقابله با

این نوع حملات وجود دارد که از جمله آنها، استفاده نکردن از توابعی همچون strcpy و gets است. این توابع

حدود بافر را بررسی نمی‌کنند و امکان دارد در آدرسی خارج از محدوده بافر، اطلاعات را بنویسند.

 

بررسی نمونه کد Stack overflow

 

Stack-code-rnpg

کد بالا، آرگومانی را از خط فرمان دریافت کرده و آن را در یک متغیر محلی به نام c که در پشته برنامه قرار دارد،

می‌نویسد. اگر آرگومانی که در خط فرمان وارد می‌شود کوچکتر از 12 باشد، این برنامه به‌درستی کار خواهد

کرد. با این حال، اگر آرگومان بزرگتر از ۱۱ کاراکتر باشد، باعث می‌شود بافر c سرریز شود (در زبان سی در

انتهای رشته‌ها یک کارکتر null قرار می‌گیرد، بنابراین حداکثر اندازه ایمن برای این بافر ۱۱ است تا یک خانه

هم برای آن کاراکتر null مهیا شود). اگر آرگومان خط فرمان ۱۲ کاراکتر باشد، برای ذخیره آن به بافری با اندازه

۱۳ نیاز است (هم خود آرگومان و هم کاراکتر null). از آنجا که بافر c تنها ۱۲ کاراکتر ظرفیت دارد، باعث

می‌شود تا کاراکتر null در خارج از محدوده بافر نوشته شود و یک خانه آن طرفتر را بازنویسی کند.

 

Stack_Overflow_rnpg

در تصویر شماره 3، وقتی که آرگومانی بزرگتر از ۱۱ کاراکتر در خط فرمان وارد می‌شود، تابع foo()‎ داده‌های

موجود در پشته برنامه، از جمله اشاره‌گر قاب ذخیره شده و از همه مهمتر، آدرس برگشت تابع را بازنویسی

می‌کند. وقتی که اجرای تابع foo()‎ به اتمام می‌رسد و تابع برمی‌گردد، برنامه آدرس برگشت تابع را از پشته

برداشته و سپس به آن آدرس پرش می‌کند و در نهایت سعی می‌کند اطلاعات موجود در آن آدرس را اجرا کند

(برنامه شروع به اجرای دستورالعمل‌های موجود در آن آدرس می‌کند). بدین گونه مهاجم آدرس برگشت تابع را

با اشاره‌گری به بافر char c[12]‎ بازنویسی می‌کند و این بافر هم اطلاعاتی را در خود دارد که توسط مهاجم به

برنامه تزریق شده‌اند. در یک حمله واقعی، اطلاعات موجود در بافر، به جای کاراکترهای  shell code ای

متناسب با پلتفرم و تابع مربوطه خواهد بود. اگر این برنامه دسترسی‌ها و امتیازات بالایی داشته باشد (مثلاً

اگر بیت SUID برای اینکه برنامه به عنوان کاربر root اجرا شود، تنظیم شده باشد)، مهاجم می‌تواند از این

آسیب‌پذیری برای بدست آوردن دسترسی root به رایانه قربانی استفاده کند.

 

حمله Heap overflow

این حمله، داده ها را در pool حافظه باز (open memory pool) که تحت عنوان Heap شناخته می شود، قرار

می دهد.

حمله Integer overflow

در یک Integer overflow، نتایج یک عملیات ریاضی در یک رشته ای که حافظه کافی ندارد، ذخیره می شود،

که می تواند منجر به سرریز شدن بافر شود.

Unicode overflow

این حمله زمانی رخ می دهد که در یک ورودی که مقدار کاراکتر های ASCII می پذیرد، از کاراکتر های

Unicode استفاده شود.

 

Buffer Overflow و نرم افزار های کاربردی وب

هکر ها از این حملات برای از دسترس خارج نمودن نرم افزار و اختلال در آن استفاده می کنند و با ارسال یک

دستور مخرب از طریق ورودی کاربر به سمت یک نرم افزار اقدام به اجرای کد دلخواه خود می نمایند. حفره

امنیتی Buffer Overflow می تواند در وب سرور و یا وب اپلیکیشن که بخش ایستا و پویا یک سایت را ارائه

می دهند، وجود داشته باشد. زمانیکه وب اپلیکیشن ها از کتابخانه ها، مانند کتابخانه گرافیکی برای تولید

تصاویر استفاده می کنند، خود را در معرض اینگونه حملات قرار می دهند.

همچنین Buffer Overflow در کدهای سفارشی وب اپلیکیشن یافت می شود و حتی ممکن است با توجه به

عدم بررسی دقیق برنامه های وب، احتمال وقوع این آسیب پذیری افزایش یابد.

دلیل اینکه آسیب پذیری مذکور در وب اپلیکیشن های سفارشی کمتر تشخیص داده می شوند، این است که

به طور معمول تعداد بسیاری از هکر ها سعی می کنند چنین نقص هایی را در یک برنامه خاص پیدا و بهره

برداری نمایند.

 

جلوگیری در برابر حملات buffer overflow

خوشبختانه، سیستم عامل های مدرن دارای محافظ های runtime می باشند که به کاهش اینگونه حملات

کمک می کنند.

دو راهکار محافظت در برابر حملات buffer overflow به شرح زیر می باشد:

 

Address space randomization

به طور تصادفی، مکان فضای آدرس مناطق داده های کلیدی یک فرآیند را مرتب می کند. حملات سرریز بافر

عموماً به دانستن محل دقیق کد مهم اجرائی متکی است، که تصادفی نمودن فضاهای آدرس، تقریباً این امر

را غیر ممکن می سازد.

 

پیشگیری از اجرای داده

مناطق خاصی از حافظه را به صورت اجرایی یا غیر اجرایی علامت گذاری می کند و مانع بهره برداری از اجرای کد موجود در یک منطقه غیر اجرایی می شود.

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

 

اجرای نمونه ساده ای از حملات Buffer Overflow بر روی سامانه آموزشی WebGoat

 

منابع:

[0] www.owasp.org
[1] www.cloudflare.com
[2] www.fa.wikipedia.org
[3] e-learnsecurity - Buffer_Overflow