IRCAR201012080
تمام برنامه هاي كاربردي تحت وب از منطق خاص خود براي عملياتي كردن وب سايت مربوطه استفاده مي كنند. نوشتن كد با استفاده از يك زبان برنامه نويسي در اصل چيزي به جز شكستن پروسه هاي پيچيده به گام هاي منطقي كوچك، نيست. البته ترجمه يك عمليات كوچك كه براي انسان معنادار است به ترتيبي از دستورات كه براي كامپيوتر قابل اجرا باشند، كاري است كه نياز به تجربه و مهارت فراواني دارد و از طرف ديگر نوشتن كد مذكور به صورتي كه امن و قابل اعتماد باشد، نيز كاري به مراتب دشوارتر است. زماني كه تعداد زيادي طراح و برنامه نويس به صورت موازي بر روي يك برنامه كاربردي كار مي كنند، به احتمال بسيار زياد مشكلات امنيتي متعددي بروز خواهند كرد. حتي در ساده ترين برنامه هاي تحت وب نيز منطق گسترده اي در هر گام برنامه وجود دارد و اين امر منجر به ايجاد سطح حمله اي مي شود كه اغلب از آن چشم پوشي مي گردد. بسياري از تست نفوذها و مرور كدها بر روي آسيب پذيري هاي اصلي همچون تزريق SQL و يا cross-site-scripting تمركز مي كنند، زيرا آسيب پذيري هاي مذكور داراي امضاي قابل تشخيص بوده و در مورد بردارهاي حمله آنها به اندازه كافي تحقيق شده و اطلاعات وجود دارد. در نقطه مقابل، شناسايي آسيب پذيري هاي موجود در منطق برنامه بسيار سخت است، زيرا هر نمونه آسيب پذيري ممكن است تنها يك بار و براي يك برنامه خاص اتفاق بيفتد كه قابل تشخيص توسط ابزارهاي اتوماتيك شناسايي آسيب پذيري ها نيست. به همين دليل به آسيب پذيري هاي مذكور چندان توجه نشده و اين امر موجب مي شود علاقه هكرها به شدت جلب اين دسته از نقص هاي امنيتي شود.
در اين مقاله در مورد انواع نقص هاي منطقي كه اغلب در برنامه هاي كاربردي تحت وب وجود دارند، صحبت خواهيم كرد.
طبيعت نقص هاي امنيتي منطقي
همان طور كه گفته شد نقص هاي امنيتي در برنامه هاي كاربردي تحت وب، بسيار متفاوت از يكديگر هستند. برخي از آنها ممكن است به راحتي قابل تشخيص و برطرف كردن باشند و برخي ديگر ممكن است از انواع تست نفوذها و مرور كدها جان سالم به در برند. اين آسيب پذيري ها بر خلاف آسيب پذيري هاي تزريق SQL و يا cross-site-scripting داراي امضاها و رفتارهاي مشخص نيستند. تنها ويژگي مشترك در آنها ناقص بودن منطق برنامه است كه در اغلب موارد به علت پيش فرض هاي واضح و يا نهان برنامه نويسان به وجود مي آيد. در حالت كلي يك برنامه نويس ممكن است استنتاج كند كه " اگر "A" اتفاق بيفتد، آنگاه "B" اتفاق مي افتد و من بايد "C" را انجام بدهم، اما برنامه نويس از خود سوال كاملاً متفاوتي نمي كند كه "چه روي خواهد داد اگر "X" اتفاق بيفتد؟" و به اين ترتيب نمي تواند سناريويي را كه از فرض مورد نظر پيروي نمي كند، مديريت نمايد. در موقعيت هاي مختلف فرض ناقص مي تواند منجر به بروز آسيب پذيري هايي با درجه اهميت متفاوت شود. در ادامه با چند مثال واقعي در مورد فرض هاي ناقص بيشتر توضيح ميدهيم.
تغيير رمز عبور
در اين مثال، يك برنامه كاربردي تحت وب متعلق به يك شركت مالي، داراي يك تابع تغيير رمز عبور براي كاربران نهايي است. براي تغيير رمز عبور كاربر بايد رمز عبور قديمي خود را وارد كرده و پس از آن رمز عبور جديد را وارد كند. همچنين بايد رمز عبور جديد را دوباره تأييد كند تا فعال شود. در اين برنامه مديران مي توانند رمز عبور هر كاربر را بدون نياز به دانستن رمز عبور قديمي تغيير دهند. اين دو برنامه در يك اسكريپت سرور پياده سازي شده اند.
String existingPassword = request.getparameter("existingPassword"); If (null == existingPassword) { Trace("Old password not supplied, must be an administrator"); Return true; } Else { Trace(" verifying user's old password"); …
برنامه نويسان فرض كرده اند در صورتي كه رمز عبور قديمي دريافت نشود، كاربر مدير بوده و اين امر با مشكلي مواجه نمي شود. آسيب پذيري در اينجا به وضوح قابل مشاهده است. يك مهاجم مي تواند بدون در دست داشتن رمز عبور فعلي، رمز عبور هر كاربري را تغيير داده و كنترل كامل حساب كاربري را در اختيار خود گيرد.
در اينجا نقص فرض در اين است كه برنامه نويس حالتي را كه كاربر عادي كلمه عبور فعلي خود را وارد نكند، در نظر نگرفته است. به همين منظور به برنامه نويسان توصيه مي شود حالت هاي مختلف وجود و يا عدم وجود اطلاعات براي هر پارامتر را در نظر گيرند.
پروسه هاي چند مرحله اي
اين مثال مربوط به يك برنامه كاربردي تحت وب متعلق به يك فروشگاه آنلاين است. در اين برنامه، يك پروسه به شرح زير براي سفارش محصول وجود دارد:
1- مرور كاتالوگ محصولات و اضافه كردن آيتم هاي مورد نظر به سبد خريد
2- بازگشت به سبد خريد و نهايي كردن سفارش
3- وارد كردن اطلاعات پرداخت
4- وارد كردن اطلاعات ارسال سفارش
در اينجا برنامه نويسان فرض كرده اند كه كاربران از ترتيب مورد نظر براي دسترسي به صفحات استفاده مي كنند، زيرا صفحات وب سايت آنها را به همين ترتيب هدايت مي كند. در نتيجه بنا بر فرض برنامه نويسان سفارشي كه به مرحله ارسال رسيده است، مرحله پرداخت را به درستي پشت سر گذاشته است. فرض ناقص در اين مثال اينست كه برنامه نويسان در نظر نگرفته اند كه كاربران هر قسمت از درخواست را كنترل مي كنند و بنابراين مهاجم مي تواند درخواست را به هر ترتيبي كه بخواهد ارسال كند. براي مثال مي تواند از مرحله 2 به مرحله 4 برود به اين معني كه بدون كامل كردن مرحله پرداخت به مرحله ارسال كالا برسد!
به برنامه نويسان توصيه مي شود حالت هاي مختلف ترتيب گام ها را براي پروسه هاي چند مرحله اي در نظر بگيرند.
پاك كردن ركوردهاي ثبت وقايع
اين مثال مربوط به يك برنامه گسترده است كه امكانات زيادي را در قالب توابع HelpDesk در اختيار كارمندان و مديران براي پشتيباني و مديريت يك پايگاه داده بزرگ كاربران، قرار مي دهد. بسياري از امكانات مذكور از جمله ايجاد حساب هاي كاربري و تغيير رمز عبور از لحاظ امنيتي حساس محسوب مي شوند. به همين دليل، برنامه كاربردي يك سابقه كامل از هر تغييري در سيستم و نام مسئول آن را ثبت مي كند.
اين برنامه حاوي تابعي است كه مديران با استفاده از آن مي توانند ركوردهاي ثبت وقايع را پاك كنند. با اين وجود براي جلوگيري از هرگونه سوءاستفاده از اين تابع، هر گونه كاربرد اين تابع نيز ثبت مي شود و در نتيجه مسئول پاك كردن ركوردهاي ثبت وقايع نيز مشخص است.
طراحان اين برنامه عقيده داشتند كه غير ممكن است يك كاربر خرابكار عملياتي را در سيستم انجام دهد و ردپايي از خود به جا نگذارد و حتي در صورتي كه يك مدير خرابكار تمام ركوردهاي ثبت وقايع را پاك كند، رد پاي خود او در سيستم به جا مي ماند.
فرض ناقص در اينجا مربوط به حوزه اختيارات مديران سيستم است، زيرا در اين برنامه مديران سيستم مي توانند كاربر جديدي را با حق دسترسي مدير ايجاد كنند و توسط كاربر مذكور به عمليات خرابكارانه بپردازند. در اين حالت مدير خرابكار مي تواند بعد از انجام حمله، توسط كاربر جديد تمام ركوردهاي ثبت وقايع را پاك كرده و به اين ترتيب ركورد ثبت مسئول ايجاد كننده كاربر مذكور را نيز از بين ببرد.
در قسمت بعدي چندين مثال ديگر را در مورد فرض هاي ناقص در منطق برنامه توضيح مي دهيم.
- 11