حمله‌های مبتنی بر سواستفاده از تابع بازگشت از سیگنال

حمله‌های مبتنی بر سواستفاده از تابع بازگشت از سیگنال  یا به اختصار SROP، یک نوع روش نفوذ است که به مهاجم اجازه می‌دهد تا کد دلخواه خود را در شرایطی اجرا کند که سازوکارهای امنیتی مانند حافظهٔ غیرقابل اجرا و امضای کد در سیستم وجود داشته باشد. این روش برای اولین بار در سی‌وپنجمین کنفرانس IEEE Security and Privacy در سال ۲۰۱۴ مطرح شد که توانست برندهٔ عنوان بهترین مقالهٔ دانشجویی شود. پیش‌فرض‌ها و ایدهٔ کلی این روش مشابه روش (ROP)برنامه‌نویسی بازگشت-مبنا است: مهاجم کنترل پشته را با روش‌هایی مثل استفاده از آسیب‌پذیری «خطای سرریز حافظهٔ پشته» به‌دست می‌گیرد و با استفاده از پشته، بر جریان اجرای دستورهای برنامه تأثیر می‌گذارد که این کار توسط دنباله‌ای از دستورها که ابزارک نام دارند انجام می‌شود. این حمله به‌این‌صورت انجام می‌گیرد که مهاجم یک داده‌ساختار sigcontext جعلی در بالای پشته قرار می‌دهد و آدرس بازگشت تابع را به یک ابزارک تغییر می‌دهدکه این ابزارک، فراخوان سیستمی sigreturn را صدا می‌زند. معمولاً یک ابزارک برای موفقیت این حمله کفایت می‌کند (برعکس ROP که معمولاً از زنجیره‌ای از ابزارک‌ها استفاده می‌کند). درصورتی‌که محل این ابزارک در حافظهٔ مجازی فرایند مورد نظر ثابت باشد این حمله بسیار ساده و مؤثر انجام می‌گیرد (مثلاً زمانی که سازوکار تصادفی‌سازی فضای آدرس‌دهی حافظه غیرفعال باشد) هم‌چنین این باعث می‌شود تا آماده‌سازی اولیهٔ بسیار ساده‌تر شود و نسبت به روش ROP قابل حمل‌تر باشد.

می‌توان SROP را یک ماشین غیرقابل پیشبینی درنظر گرفت زیرا اجازه می‌دهد کدهایی خارج از محدودهٔ تعیین شده برای برنامه، اجرا شوند.

 پیش‌زمینه 
SROP شباهت زیادی به روش ROP دارد و این شباهت از این جهت است که در این روش هم مهاجم از کدهای موجود در برنامه (کدهای موجود در حافظهٔ برنامه) استفادهٔ مجدد می‌کند تا برنامهٔ قربانی را وادار کند خارج از چارچوب تعیین شده عمل کند. برای این کار مهاجم باید داده‌های پشته را تغییر دهد که این کار معمولاً با استفاده از روش «سرریزحافظهٔ پشته» صورت می‌گیرد که هدف آن تغییر آدرس بازگشت موجود در پشته است.

 روش پرش از پشته (Stack hopping exploit) 
اگر سازوکار «منع اجرای داده» یا همان DEP در سیستم فعال باشد مهاجم قادر نخواهد بود تا کدهای تزریقی موردنظر خود را مستقیماً در پشته بنویسد و با بازنویسی آدرس بازگشت، سیستم را وادار به اجرای کدها کند. با فعال بودن چنین سازوکاری، سیستم کدهایی که در صفحات حافظه با برچسب «غیرقابل اجرا» هستند را اجرا نمی‌کند؛ بنابراین مهاجم باید سعی کند تا با استفادهٔ مجدد از کدهایی که درحال‌حاضر در حافظهٔ برنامه، موجود هستند به هدف خود برسد.

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

در روش ROP به دنباله‌ای از این دستورالعمل‌ها که به آن‌ها ابزارکs گفته می‌شود نیاز داریم و ویژگی مشترک همهٔ این دنباله‌ها این است که در انتهای همهٔ آن‌ها یک دستورالعمل RET وجود دارد. مهاجم با قرار دادن یک دنباله از آدرس‌های بازگشت در پشته می‌تواند بعد از اجرای یک ابزارک و رسیدن به دستورالعمل RET، سیستم را وادار کند تا ابزارک بعدی را اجرا کند و اینگونه با تعیین ترتیب اجرای ابزارک‌ها، به هدف خود برسد.

 سازوکار پردازش سیگنال (Signal handler mechanism) 
چپ|بندانگشتی| محتوای پشته هنگام پردازش یک سیگنال (linux x86 / 64) شامل داده‌ساختار sigcontext
این نوع حمله براساس نحوهٔ پردازش سیگنال‌ها در سیستم‌عامل‌هایی که بر پایهٔ POSIX هستند، طراحی شده‌است. زمانی که یک سیگنال به یک فرایند می‌رسد، هستهٔ سیستم‌عامل باید یک عملیات تغییر بافتار به پردازش‌گر سیگنال (که از قبل در سیستم ثبت شده‌است) انجام دهد. برای انجام این کار، هسته باید مقدار بافتار فعلی را در یک قاب بر روی پشته ذخیره کند. داده‌ساختاری که بر روی پشته ذخیره می‌شود بسته به معماری سیستم متفاوت است و معمولاً sigcontext نام دارد که داده‌هایی مثل مقادیر ثباتها در زمان تغییر بافتار را درخود نگه می‌دارد. زمانی که کار پردازش‌گر سیگنال به اتمام رسید فراخوان سیستمی ()sigreturn صدا زده می‌شود (این فراخوان وظیفه دارد بافتار قبلی فرایند را با استفاده از داده‌ساختار sigcontext بازیابی کند).

فراخوانی sigreturn به این معناست که می‌توان به سادگی مقادیر ثبات‌ها پردازنده را به وسیلهٔ یک ابزارک که به سادگی در سیستم یافت می‌شود، تغییر داد.

 تفاوت‌های SROP و ROP 
چندین عامل برای تشخیص و تفکیک روش SROP از روش سنتی ROP وجود دارد.

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

با این وجود کامپایلرهایی طراحی و پیاده‌سازی شده‌اند که قادراند زنجیرهٔ ابزارک‌ها را به شکل Turing-complete استخراج کنند.

درصورت استفاده از SROP این امکان وجود دارد که بتوان روشی که برای نفوذ به یک فایل دودویی خاص طراحی شده برای یک فایل دودویی دیگر استفاده کرد (قابل حمل بودن) که معمولاً یا هیچ نیازی به تغییر طراحی نیست یا تغییرات بسیار ناچیز است و هم‌چنین همیشه امکان تغییر محتویات ثبات‌ها در این روش برای مهاجم وجود دارد درحالی‌که اگر از روش ROP استفاده شود و در برنامه ابزارک‌هایی یافت نشوند که امکان تغییر محتویات ثبات‌ها را داشته باشند، کار برای مهاجم بسیار سخت و حتی غیرممکن خواهد شد. علاوه بر موارد بالا، SROP به حداقل تعداد ابزارک‌ها نیاز دارد و به مهاجم اجازه می‌هد تا با اجرای زنجیروار فراخوان‌های سیستمی، به‌صورت مؤثر اقدام به طراحی و اجرای shellcode موردنظر خود کند. ابزارک‌های ذکر شده همیشه در حافظه موجود هستند و حتی در مواردی آدرس آن‌ها نیز ثابت و مشخص است:
+ لیست ابزارک‌ها در سیستم‌های مختلف سیستم عامل ASLR اسباب بازی نقشه حافظه مکان حافظه ثابت لینوکس i386  sigreturn [vdso] لینوکس <3.11 ARM sigreturn [vectors] 0xffff0000 لینوکس <3.3 x86-۶۴ syscall&return [vsyscall] 0xffffffffff600000 لینوکس 3.3 x86-۶۴  syscall&return Libc لینوکس x86-64  sigreturn Libc FreeBSD 9.2 x86-64 sigreturn 0x7ffffffff000 Mac OSX x86-64  sigreturn Libc iOS ARM  sigreturn Libsystem iOS ARM  syscall&return Libsystem

 حمله‌ها 
 لینوکس 
به‌عنوان یک مثال از ابزارک‌هایی که همیشه در حافظهٔ VDSO در لینوکس ۳۲-بیتی وجود دارند و برای استفادهٔ SROP مناسب هستند می‌توان به مورد زیر اشاره کرد: __kernel_sigreturn proc near:
pop   eax
mov   eax, 77h
int   80h ; LINUX - sys_sigreturn
nop
lea   esi, [esi+0]
__kernel_sigreturn endp در بعضی از نسخه‌های هسته لینوکس درصورتی‌که محدودیت اندازهٔ پشته را «نامحدود» تنظیم کنیم، سازوکار ASLR غیرفعال می‌شود که این باعث می‌شود تا مهاجم به‌صورت مؤثر ASLR را دور بزند و به‌راحتی به ابزارک‌های موجود در VSDO دسترسی پیدا کند.

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

 کامل بودن از نظر تورینگ (Turing-completeness) 
این امکان وجود دارد تا با استفاده از ابزارک‌ها اطلاعاتی را در قاب‌های پشته بنویسیم یا تغییر دهیم که در این‌صورت یک برنامهٔ خود-متغیر خواهیم داشت. با استفاده از این روش می‌توانیم یک ماشین مجازی ساده بسازیم و از آن به‌عنوان مترجم برای یک زبان Turing-complete استفاده کنیم. یک مثال از این رویکرد را می‌توان در مقالهٔ Bosman پیدا کرد که در آن نحوهٔ ساخت یک مفسر برای یک زبان مشابه با زبان برنامه‌نویسی Brainfuck توضیح داده شده‌است. این زبان یک اشاره‌گر به دستورالعمل PC، یک اشاره‌گر به حافظه P و یک ثبات موقت ۸-بیتی A برای جمع داشت. این بدان معناست که این امکان وجود دارد که درهای پشتی یا حمله‌های گمراه‌کننده را نیز طراحی و اجرا نمود.

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

 تصادفی‌سازی فضای آدرس حافظه (ALSR) 
ASLR یا تصادفی‌سازی فضای آدرس‌دهی باعث می‌شود تا محل ذخیره‌سازی ابزارک‌ها برای مهاجم غیرقابل پیشبینی شود که این باعث می‌شود تا استفاده از ابزارک‌های موردنظر مشکل شود.

 استفاده از روش «شیرینی» برای سیگنال‌ها 
یکی از روش‌های مقابله با حملات SROP استفاده از روش «شیرینی» است. در این روش، سیستم قبل از بازیابی بافتار، اصالت داده‌ساختار sigcontext ذخیره شده در پشته را بررسی می‌کند و اطمینان حاصل می‌کند که داده‌های آن جعل نشده باشند. نحوهٔ انجام این کار به این‌صورت است که سیستم یک شیرینی (عدد) به‌صورت تصادفی انتخاب کرده و آن را با آدرس ذخیره‌سازی در پشته (جایی که شرینی باید ذخیره شود) xor می‌کند. در این‌صورت تنها کاری که فراخوان سیستمی sigreturn باید انجام دهد این است که بررسی کند این شیرینی در مکان تعیین‌شده وجود داشته باشد. این روش به‌صورت مؤثر و با حداقل سربار ممکن (حداقل کاهش کارایی)، قادر به جلوگیری از حمله‌های SROP است.

 شبیه‌سازی Vsyscall 
در لینوکس‌هایی با نسخه‌های بالاتر از ۳٫۳ رابط vsyscall به‌گونه‌ای شبیه‌سازی شده‌است که درصورتی‌که هرگونه تلاش برای اجرای مستقیم ابزارک‌ها (اجرای بخشی از تابع) صورت گیرد، سیستم یک استثنا ایجاد می‌کند.

 حفاظت از آدرس بازگشت (RAP) 
مجموعه‌ای از وصلهها با نام Grsecurity برای هسته‌ی لینوکس ارائه شده که امنیت آن را بهبود بخشیده‌است. این مجموعه شامل سازوکاری به‌نام RAP (Return-Address Protection) یا «حفاظت از آدرس بازگشت» که از حمله‌های «استفادهٔ مجدد از کدهای موجود» جلوگیری می‌کند.

 کنترل جریان اجباری (CET) 
از سال ۲۰۱۶ شرکت اینتل شروع به توسعهٔ تکنولوژی کنترل جریان اجباری یا همان CET کرد. این تکنولوژی از حملات «پرش از پشته» جلوگیری می‌کند. نحوهٔ عملکرد آن به این‌صورت است که علاوه‌بر پشتهٔ معمولی یک پشتهٔ دیگر به‌عنوان «پشتهٔ سایه» درنظر گرفته می‌شود که فقط اطلاعات مربوط به آدرس بازگشت در آن ذخیره می‌شود و این پشته توسط واحد «مدیریت حافظه» که یک واحد سحت‌افزاری است و در CPU قرار دارد محافظت می‌شود.

 جستارهای وابسته 
 Linux kernel interfaces
 آسیب‌پذیری
 اکسپلویت
 سرریز بافر
 تصادفی کردن چیدمان فضای آدرس
 حفاظت از فضای آدرس اجرایی
 NX bit

 منابع 

 پیوند به بیرون 
 OHM 2013: Review of “Returning signals for fun and profit
 Playing around with SROP 
 Fun with SROP Exploitation
 binjitsu - Sigreturn Oriented Programming
 SigReturn Oriented Programming on x86-64 linux
 Sigreturn ROP exploitation technique (signal's stack frame for the win)
رده:سوءاستفاده امنیتی از رایانه
رده:صفحات با ترجمه بازبینی‌نشده