موضوع مقاله: محافظت در برابر سرریز بافر | مخاطب: عمومی | لحن: دانشنامه‌ای | ساختار: عنوان، مقدمه، 3 بخش، جمع‌بندی | مقاله: | # محافظت در برابر سرریز بافر | مقدمه: سرریز بافر پشته زمانی اتفاق می‌افتد که یک برنامه، اطلاعاتی را در آدرسی از حافظه (معمولاً بافر با طول ثابت)، خارج از ساختمان داده مورد نظر می‌نویسد. | ## بخش 1: محافظت در برابر سرریز بافر | اشکال سرریز بافر پشته زمانی اتفاق می‌افتد که یک برنامه حجم داده‌ای بیشتر از حجم بافر اختصاص داده شده را در حافظه می‌نویسد. نتیجه این عمل خراب شدن و آسیب دیدن اطلاعات مجاور آن بافر در پشته است و در صورتی که این سرریز به‌طور ناخواسته و بر اساس یک اشتباه به وجود آمده باشد، اغلب باعث می‌شود که برنامه کرش کند، به صورت نادرست رفتار کند یا به منجر به مشکلات امنیتی شود. به طور معمول، محافظت در برابر سرریز شدن، سازمان داده‌های اختصاص داده شده از پشته را تغییر می‌دهد. به عنوان مثال یک مقدار canary به پشته اضافه می‌کند که در زمان سرریز شدن بافر پشته خراب می‌شود که نشان دهنده این است که حافظه دچار سرریز شدن شده است. با اعتبار سنجی مقدار canary، اجرای برنامه تحت تاثیر خاتمه پیدا می‌کند و از اجرای رفتارهای نادرست و همچنین در دست گرفتن کنترل برنامه توسط مهاجم جلوگیری می‌کند. سرریز بافر در پشته به دلیل داشتن آدرس بازگشت توابع باعث به هم خوردن مسیر اجرای برنامه می‌شود در حالی که در سرریز بافر هیپ این اتفاق کم رنگ تر است. با این حال روش‌های پیاده سازی مشابه برای محافظت در برابر سرریز شدن بافر در هیپ وجود دارد. چندین پیاده سازی از محافظت در برابر سرریز بافر شامل مجموعه کامپایلر گنو، LLVM، مایکروسافت ویژوال استودیو و سایر کامپایلرها وجود دارد. بررسی اجمالی سرریز بافر پشته زمانی اتفاق می‌افتد که یک برنامه، اطلاعاتی را در آدرسی از حافظه (معمولاً بافر با طول ثابت)، خارج از ساختمان داده مورد نظر می‌نویسد. اشکال سرریز بافر پشته زمانی اتفاق می‌افتد که یک برنامه حجم داده ای بیشتر از حجم بافر اختصاص داده شده را در حافظه می‌نویسد. نتیجه این عمل خراب شدن و آسیب دیدن اطلاعات مجاور آن بافر در پشته است و در صورتی که این سرریز به‌طور ناخواسته و بر اساس یک اشتباه به وجود آمده باشد، اغلب باعث می‌شود که برنامه کرش کند یا به صورت نادرست رفتار کند. این نوع سرریز، بخشی از دسته بزرگتری از باگ‌های برنامه‌نویسی به نام سرریز بافر است. سرریز بافر در پشته به دلیل داشتن آدرس بازگشت توابع باعث به هم خوردن مسیر اجرای برنامه می‌شود در حالی که در سرریز بافر هیپ این اتفاق کم رنگ تر است. اگر برنامه آسیب دیده با سطح دسترسی خاصی در حال اجرا باشد یا داده‌های ورودی خود را از شبکه‌های نامطمئن دریافت کند (به عنوان مثال یک وب سرور عمومی)، این اشکال یک آسیب پذیری امنیتی بالقوه است که به مهاجم اجازه می‌دهد کدهای قابل اجرا را به برنامه تزریق کند و کنترل روند برنامه را به دست بگیرد. این یکی از قدیمی‌ترین و مطمئن‌ترین روش‌ها برای مهاجمین برای دستیابی دسترسی غیرمجاز به کامپیوتر است. به طور معمول، محافظت در برابر سرریز بافر، ساختار داده‌های فراخوانی تابع در قاب پشته را برای افزودن مقدار canary تغیر می‌دهد. زمانی که این مقدار تخریب شود نشان دهنده این است که حافظه دچار سرریز بافر شده است و باعث جلوگیری از حملات سرریز بافر می‌شود. هیچ روش کاربردی برای تغییر طرح داده در یک ساختار وجود ندارد، انتظار می‌رود ساختارها بین ماژول‌ها، به ویژه در کتابخانه‌های مشترک یکسان باشند. | ## بخش 2: محافظت در برابر سرریز بافر | بنابراین، برنامه‌نویسان باید در سازماندهی متغیرها و ساختار آن‌ها دقت کافی را داشته باشند. پس از خرابی مقدار canary هشدار سرریز بافر منتشر می‌شود و سپس می‌توان این خطا را مدیریت کرد. canaryهای خاتمه‌دهنده canaryهای خاتمه‌دهنده از این مشاهدات استفاده می‌کنند که بیشتر حملات سرریز بافر براساس عملیات‌های خاص رشته‌ای هستند که در خاتمه‌دهنده‌های رشته‌ها هستند. در نتیجه، مهاجم باید قبل از آدرس بازگشت یک مقدار تهی بنویسد تا از تغییر canary جلوگیری کند. این کار از وقوع حملات با تابع strcpy و سایر روش‌هایی که به محض کپی کردن، یک کاراکتر تهی برمی‌گردانند جلوگیری می‌کند، در حالی که نتیجه نامطلوب این است که canary شناخته می‌شود. حتی با این محافظت، مهاجم می‌تواند مقدار canary را با مقدار دلخواه خود جایگزین کند و کنترل داده‌ها را با مقادیر ناسازگار در دست بگیرد. canaryهای تصادفی این مقدار بصورت تصادفی تولید می‌شود تا مقدار آن از دید مهاجمین مخفی بماند. این مقدار امن را صرفاً کسانی می‌دانند که (مثلاً کد حفاظت در برابر سرریز بافر) نیاز است. به طور نرمال، canary تصادفی در ابتدای شروع برنامه تولید می‌شود و در یک متغیر سراسری ذخیره می‌شود. این متغیر معمولاً توسط داده‌های بدون نقشه پر شده است، بنابراین تلاش برای خواندن آن از حافظه RAM سخت خواهد شد. این مقدار ممکن است هنوز قابل خواندن باشد، اگر مهاجم بتواند این مقدار را بخواند، می‌تواند برنامه در حال اجرا از پشته بخواند. اگرچه این canaryها از داده‌های کنترلی در برابر تغییر توسط اشاره‌گرها محافظت می‌کند، آن‌ها از بقیه داده‌ها یا خود اشاره‌گرها محافظت نمی‌کنند. بخصوص اشاره‌گرهای توابع در اینجا مشکل ایجاد می‌کنند، آن‌ها می‌توانند سرریز شوند و در زمان فراخوانی shellCode اجرا کنند. بررسی کردن مرزها بررسی مرزها یک شیوه مبتنی بر کامپایلر است که اطلاعات مرزها را در زمان اجرا برای هر بلوک اختصاص داده شده از حافظه اضافه می‌کند و همه اشاره‌گرها در مقابل آن‌ها در زمان اجرا بررسی می‌کند. اشاره‌گر Fat: شامل اشاره‌گر و داده‌های اضافی که ناحیه نقطه گذاری شده را توصیف می‌کند. برچسب زدن برچسب زدن یک روش مبتنی بر کامپایلر یا سخت افزار (نیازمند معماری برچسب خورده) برای برچسب زدن نوع یک قطعه از داده در حافظه است که معمولاً برای بررسی نوع آن استفاده می‌شود. با علامت گذاری ناحیه مشخصی از حافظه به عنوان غیرقابل اجرا، بطور موثر از ذخیره کد قابل اجرا در حافظه جلوگیری می‌کند. همچنین ناحیه‌ای از حافظه را میتوان به عنوان غیر تخصیص یافته علامت گذاری کرد و از سرریز بافر جلوگیری نمود. | ## بخش 3: محافظت در برابر سرریز بافر | از جنبه تاریخی، از برچسب زدن برای پیاده سازی زبان‌های برنامه نویسی سطح بالا استفاده شده است. با پشتیبانی مناسب از سمت سیستم عامل‌ها، از برچسب‌ها برای شناسایی سرریز بافر نیز استفاده می‌شود. مایکروسافت ویژوال استدیو مجموعه کامپایلرهای مایکروسافت محافظت از سرریز بافر را از سال 2003 در خط فرمان، سوئیچ پیاده سازی نمود. بدین ترتیب در این روش نیاز به تغییر سورس برنامه نیست و این محافظ بصورت خودکار تمام برنامه را محافظت می‌کند. مثال از canary تخصیص بافر معمولی برای معماری‌های x86 و سایر معماری‌های مشابه در سرریز بافر نشان داده شده است. بنابراین، اجرای قطعه آخر از داده‌ها در یک فریم پشته، داده‌های قبلی که قبلاً وارد فریم پشته شدند را تغییر می‌دهد و اجرای انتها یک فریم پشته داده‌ها در فریم پشته قبلی قرار می‌دهد. هر قطعه از داده‌ها که در فراخوانی ایجاد می‌شود به ترتیب در پشته قرار می‌گیرد، بنابراین از انتها تا ابتدا حافظه مرتب می‌شوند. CTLI RETA) در این وضعیت فرضی، اگر بیش از ده بایت در آرایه c، یا بیش از 13 بایت در آرایه کاراکتری d نوشته شود، مازاد آن در اشاره‌گر عدد صحیح b، سپس در عدد صحیح a، پس از آن در دستورات کنترلی و در نهایت در آدرس بازگشت سرریز می‌شود. با بازنویسی b، اشاره‌گر می‌تواند به مکانی از حافظه اشاره کند و در نتیجه هر آدرس دلخواهی از حافظه را بخواند. با بازنویسی RETA، تابع می‌تواند کد دیگری را اجرا کند (در زمانی که قصد بازگشت دارد). این کد می‌تواند از بین توابع موجود، یا کدهای نوشته شده در پشته در زمان سرریز باشد. به طور خلاصه، مدیریت ضعیف متغیرهای d و c، مانند فراخوانی strcpy در بدون تعیین مرز بالا، می‌تواند به مهاجمین اجازه دهد برنامه را با مقادیر منتسب شده در c و d بطور مستقیم کنترل کند. برای امن کردن تابع بالا، ترتیب زیر بصورت خودکار تنظیم می‌شود: آرایه c و d در ابتدا فریم پشته قرار می‌گیرند که در نتیجه اعداد صحیح a و b قبل از آن‌ها در حافظه قرار می‌گیرند. متغیرهای خودکار تابع بالا را بخواهند صفحاتی دوباره مرتب با خیال راحت تر است: آرایه‌ها و برای اولین بار در قاب پشته اختصاص داده، که مکان صحیح و اشاره گر عدد صحیح قبل از آنها در حافظه است. بنابراین، برای یک حمله موثر به برنامه، مهاجم باید مقدار canary را دست نخورده باقی بگذارد. روش canary قبل از هر اختصاص پویای بافر و بعد از هر جداسازی پویای بافر یکسری دستورالعمل سربار اضافه می‌کند. اگر مهاجم بداند canary وجود دارد، مقدار آن چیست و موقعیت آن کجاست، می‌تواند مقدار آن را بدون تغییر نگه دارد. | ## جمع‌بندی | موقعیت قرارگیری مقدار canary در پیاده‌سازی مشخص می‌شود، اما همیشه بین بافر و داده‌های محافظت‌شده قرار دارد.