فا

‫ برنامه‌نويسي امن با زبان C – سيگنالها - قسمت دوم

IRCAR201104095
تاريخ: 26/01/90
عنصر اصلي در برنامه‌نويسي امن با زبان‌هاي مختلف برنامه‌نويسي، مستندسازي خوب و استفاده از استانداردهاي قابل اجرا است. استانداردهاي كدنويسي، برنامه نويسان را ترغيب به پيروي از مجموعه‌اي متحدالشكل از قوانين و راهنمايي‌هايي مي‌كند كه بر اساس نيازمندي‌هاي پروژه و سازمان تعيين شده است، نه بر اساس سلايق و مهارت‌هاي مختلف برنامه‌نويسان. به محض تعيين استانداردهاي مذكور، ميتوان از آن به عنوان معياري براي ارزيابي كدهاي منبع، چه به صورت دستي و چه به صورت اتوماتيك استفاده كرد.
از استانداردهاي معروف در اين زمينه مي‌توان به استانداردCERT براي كدنويسي امن اشاره كرد كه يك سري از قوانين و پيشنهادات را براي كدنويسي امن با زبان‌هاي برنامه‌نويسي C، C++ و جاوا ارائه مي‌دهد. هدف از اين قوانين و پيشنهادات، حذف عادت‌هاي كدنويسي ناامن و رفتارهاي تعريف نشده است كه منجر به آسيب‌پذيري‌هاي قابل سوءاستفاده مي‌شود. به كارگيري استانداردهاي مذكور منجر به توليد سيستم‌هاي با كيفيت بالاتر مي‌شود كه در برابر حملات بالقوه، پايدارتر و مقاوم‌تر هستند.
در مقاله هاي قبلي، كليات استاندارد CERT در زمينه مزبور را توضيح داديم و در سري مقاله‌هاي برنامه‌نويسي امن به زبان C به صورت تخصصي‌تر شيوه برنامه‌نويسي امن با اين زبان را مورد بررسي قرار مي‌دهيم. قابل ذكر است كه در اين استاندارد 89 قانون و 134 پيشنهاد براي برنامه‌نويسي امن با زبان C ارائه شده است كه در اين سري مقالات، مهمترين آنها را كه در سطح يك قرار دارند، شرح خواهيم داد. براي كسب اطلاعات بيشتر در مورد سطح‌بندي قوانين و پيشنهادات به مقاله "آشنايي با استاندارد CERT براي برنامه نويسي امن" مراجعه فرماييد. در مقاله حاضر به يك قانون باقيمانده از قوانين ارائه شده سطح اول در مورد سيگنالها خواهيم پرداخت.
40. ENV32-C در سيگنالها longjmp() را فراخواني نكنيد.
فراخواني تابع longjmp() درون يك تابع تك منظوره سيگنال (signal-handler) در صورتي كه منتج به فراخواني يكي از توابعي بشود كه جزء توابع امن غير همزمان نيست، منجر به بروز رفتار تعريف نشده خواهد شد و ممكن است هكر بتواند كنترل برنامه را در اختيار بگيرد. در نتيجه توابع longjmp() و POSIX siglongjmp() نبايد هيچگاه درون يك تابع تك منظوره سيگنال فراخواني شوند.
اين قانون كاملاً به قانون "ENV04-C – در سيگنالها فقط توابع غيرهمزمان امن را فراخواني كنيد" مربوط است. فراخواني longjmp() از درون يك تابع تك منظوره سيگنال منجر مي شود تا كدي كه بعد از setjmp() قرار دارد، با همان شرايط و اولويت هايي كه خود تابع سيگنال دارد، فراخواني شود. اين بدين معني است كه كد مذكور زماني فراخواني مي شود كه داده هاي عمومي در وضعيت با ثباتي قرار ندارند و اين امر ممكن است منجر به خرابي برنامه شود. بنابراين خطر فراخواني longjmp() درون يك تابع تك منظوره دقيقاً مشابه خطري است كه فراخواني توابع غير امن غير همزمان درون يك چنين توابعي دارند. اين خطر منجر به افزايش حق دسترسي و يا ديگر حملات مي شود.
برنامه اي را كه در زير مشاهده مي كنيد از اين قانون پيروي نكرده است. اين برنامه بسيار به يك آسيب پذيري كه در تابع Sendmail وجود داشت، شباهت دارد. در اين برنامه يك قطعه كد درون يك حلقه در main() اجرا مي شود و همچنين برخي داده ها را نيز ثبت مي كند. به محض دريافت يك SIGINT، كنترل برنامه به خارج از حلقه منتقل شده، پيغام خطا ثبت شده و برنامه پايان مي پذيرد.
يك هكر مي تواند از اين برنامه به طريقي سوءاستفاده كند كه يك SIGINT را درست قبل از if دوم در log_message توليد كند. اين باعث مي شود كه longjmp() كنترل برنامه را به main() برگرداند، جايي كه log_message() دوباره فراخواني مي شود. به هر حال، در اينجا if اول نبايد دوباره اجرا شود زيرا مقدار buf به علت بروز وقفه برابر با null نشده است و برنامه ممكن است بر روي قسمت نادرستي از حافظه با نام buf0 بنويسد.
در برنامه اصلاح شده زير، فراخواني longjmp() حذف شده است و تابع تك منظوره سيگنال يك پرچم خطا از نوع volatile sig_atomic_t را تنظيم مي كند.

نظرات

بدون نظر
شما برای نظر دادن باید وارد شوید

نوشته

 
تاریخ ایجاد: 18 مرداد 1393

دسته‌ها

امتیاز

امتیاز شما
تعداد امتیازها: 0