PDA

مشاهده نسخه کامل : کنترل و حذف سرريزي بافر در برنامه‌ها



Saeed-Milan
12-02-10, 19:11
کنترل و حذف سرريزي بافر در برنامه‌ها
برنامه‌نويسي به‌سبک پترس
يکي از مشکلات امنيتي که در بعضي از نرم‌افزارها مشاهده مي‌شود، سرريزي‌بافر يا Buffer Overflow است. سرريزي بافر عموما در زمان اجرا و بسته به ورودي‌هاي مختلف برنامه رخ مي‌دهد و حتي مي‌تواند به هکرها کمک کند تا برنامه را تغيير داده و کدهاي مخرب در آن وارد کنند. در اين مقاله قصد داريم اين موضوع را بررسي کنيم و ببينيم سرريزي بافر چيست و چه‌زماني اتفاق مي‌افتد.

Only the registered members can see the link (Only the registered members can see the link)
بافر چيست؟

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

1 در سطح سيستم‌عامل: سيستم‌عامل مقداري از حافظه را جهت بافرکردن به‌خود‌اختصاص مي‌دهد. اين حافظه براي يکسان‌سازي سرعت ديسک سخت و پردازشگر استفاده مي‌شود.

2 در سطح نرم‌افزار کاربردي: اين حافظه را ما به‌عنوان برنامه‌نويس تعريف مي‌کنيم تا امور مختلفي را انجام دهيم.

قطعه کد زير را در نظر بگيريد:‌

void overflow_function (char *str){

char buffer[10];

strcpy(buffer, str);

}

int main(){

char big_string[14];

strcpy(big_string,"BufferOverflow");

overflow_function(big_string);

return 0;

}

از لحاظ قواعد گرامري اين قطعه کد درست است و بايد بدون اشکال‌کار کند اما در زمان اجرا، خطاي در حال اجرا صادر خواهد شد با اين مضمون:

Stack around the variable ‘buffer’ was corrupted

بسيار خب، اين خطا به‌ ما مي‌گويد كه متغير بافر خراب شده است.

بياييد ببينيم اين کد دقيقا چه ‌کار مي‌کند:

ابتدا يک متغير از نوع رشته به طول 14کاراکتر تعريف کرده و مقدار BufferOverflow را با استفاده از دستور strcpy در آن کپي مي‌کنيم. تا اينجا مشکل خاصي نيست و کد درست است. حال مقدار big_string به تابع overflow_function پاس داده مي‌شود. اين تابع سعي دارد مقدار big_string که به آن داده شده است را درbuffer کپي کند اما اين عمل ناموفق مي‌ماند و در نتيجه برنامه خطا مي‌دهد. چرا خطا مي‌دهد؟

اين ‌تابع مي‌خواهد مقدار 14کاراکتر را در يک رشته 10کاراکتري کپي کند، طبيعي است که اين کار را نمي‌تواند درست انجام دهد، براي همين خطا صادر مي‌شود. کمي دقيق‌تر به مساله نگاه مي‌کنيم: وقتي تابع overflow_function فراخواني مي‌شود آدرس برگشت به تابع فراخواننده در ثبات SP قرار مي‌گيرد.

سپس اين تابع سعي مي‌کند مقدار 14کاراکتر را در 10کاراکتر کپي کند و اين عمل با موفقيت انجام مي‌شود. فرض کنيد بافر در 10خانه اول بعد از آدرس 100H قرار داد و ثبات SP مقدار خانه 10DH را به‌عنوان آدرس برگشتي تابع overflow_function در خود دارد. حال مقدار 14کاراکتر در متغير بافر، کپي مي‌شود و در نتيجه خانه‌هاي 100H تا 10EH بازنويسي مي‌شوند و سپس کار تابع به پايان مي‌رسد و سيستم‌عامل قصد دارد با استفاده از آدرس ذخيره شده در SP به فراخواننده تابع overflow_function بر گردد اما از آن‌جايي که آدرس 10DH بازنويسي شده است، پردازشگر نمي‌تواند دستوري را اجرا کند و خطاي BufferOverflow صادر مي‌شود. خب، هکرها با استفاده از همين خطا به سيستم‌هاي ديگران حمله مي‌کنند. آنها يکسري دستورات به زبان اسمبلي مي‌نويسند که در اصطلاح به آنها ShellCode يا Exploit گفته مي‌شود.

به‌مثال بالا برمي‌گرديم، فرض کنيد به‌جاي مقدار “BufferOverflow” يک شل کد به تابع overflow_function داده شود. وقتي کار تابع تمام شد، پردازشگر به آدرس 10DH مي‌رود. مقدار اين آدرس ديگر يک مقدار نامعتبر نيست بلکه به يک قطعه کد اشاره دارد و پردازشگر، آن قطعه کد را اجرا مي‌کند و سبب مي‌شود برنامه اصلي، کار خودش را درست انجام ندهد‌. اين يک روش براي سوءاستفاده از سرريزي است. روش ديگر دسترسي به بخش‌هاي محرمانه حافظه است که اطلاعات اساسي سيستم در آن قرار دارد. هکر با تزريق کد خود به برنامه مي‌تواند به بخش‌هاي محرمانه حافظه دسترسي پيدا کند و اطلاعات حياتي سيستم را مورد سو‌ءاستفاده قرار دهد.

چگونه جلوي سرريزي را بگيريم؟

تنها کاري كه لازم است انجام دهيم، بررسي مقادير ورودي برنامه است تا دقيقا مطابق با اندازه متغير داده‌ها درون آن ريخته شوند. به‌طور مثال؛ کد بالا را با تغيير کوچکي اصلاح مي‌کنيم و از سرريزي بافر جلوگيري مي‌کنيم. کد بازنويسي‌شده به‌صورت زير خواهد بود:

void overflow_function (char *str){

char buffer[10];

strncpy(buffer, str,10);

}

int main(){

char big_string[14];

strncpy(big_string,"BufferOverflow",14);

overflow_function(big_string);

return 0;

}

اميربهاالدين سبط‌الشيخ
منبع: (Only the registered members can see the link)