اشتباهات رايج در منطق برنامه‌های تحت‌وب – قسمت دوم

اشتباهات رايج در منطق برنامه‌های تحت‌وب – قسمت دوم

تاریخ ایجاد

IRCAR201012082
تمام برنامه هاي كاربردي تحت وب از منطق خاص خود براي عملياتي كردن وب سايت مربوطه استفاده مي كنند. نوشتن كد با استفاده از يك زبان برنامه نويسي در اصل چيزي به جز شكستن پروسه هاي پيچيده به گام هاي منطقي كوچك، نيست. البته ترجمه يك عمليات كوچك كه براي انسان معنادار است به ترتيبي از دستورات كه براي كامپيوتر قابل اجرا باشند، كاري است كه نياز به تجربه و مهارت فراواني دارد و از طرف ديگر نوشتن كد مذكور به صورتي كه امن و قابل اعتماد باشد، نيز كاري به مراتب دشوارتر است. زماني كه تعداد زيادي طراح و برنامه نويس به صورت موازي بر روي يك برنامه كاربردي كار مي كنند، به احتمال بسيار زياد مشكلات امنيتي متعددي بروز خواهند كرد. حتي در ساده ترين برنامه هاي تحت وب نيز منطق گسترده اي در هر گام برنامه وجود دارد و اين امر منجر به ايجاد سطح حمله اي مي شود كه اغلب از آن چشم پوشي مي گردد. بسياري از تست نفوذها و مرور كدها بر روي آسيب پذيري هاي اصلي همچون تزريق SQL و يا cross-site-scripting تمركز مي كنند، زيرا آسيب پذيري هاي مذكور داراي امضاي قابل تشخيص بوده و در مورد بردارهاي حمله آنها به اندازه كافي تحقيق شده و اطلاعات وجود دارد. در نقطه مقابل، شناسايي آسيب پذيري هاي موجود در منطق برنامه بسيار سخت است، زيرا هر نمونه آسيب پذيري ممكن است تنها يك بار و براي يك برنامه خاص اتفاق بيفتد كه قابل تشخيص توسط ابزارهاي اتوماتيك شناسايي آسيب پذيري ها نيست. به همين دليل به آسيب پذيري هاي مذكور چندان توجه نشده و اين امر موجب مي شود علاقه هكرها به شدت جلب اين دسته از نقص هاي امنيتي شود.
در مقاله قبل در مورد طبيعت نقص هاي امنيتي منطقي كه اغلب از فرض هاي ناقص سرچشمه مي گيرند صحبت كرديم و با چندين مثال واقعي اين موضوع را روشن تر ساختيم. در اين مقاله نيز به تكميل مثال هاي مزبور مي پردازيم.

محدوديت هاي عددي
در اين مثال فرض ناقص در برنامه كاربردي يك كارخانه را مورد بررسي قرار مي دهيم. در اين برنامه كارمندان بخش مالي اجازه انتقال پول بين حساب هاي بانكي متعلق به كارخانه، مشتريان و تأمين كنندگان را دارا هستند. براي جلوگيري از هر گونه كلاهبرداري و يا اختلاس، اكثر كارمندان اجازه انتقال مبالغ بيش از 10 هزار دلار را دارا نبوده و براي اين كار بايد از مدير بالاتر خود اجازه بگيرند. اين احتياط توسط كد زير پياده سازي شده است:

Bool CAuthCheck::RequiresApproval(int amount)
{
If (amount <= m_apprTreshold)
Return false;
Else return true;
}

برنامه نويسان در اينجا فرض كرده اند كه با اين برنامه هيچ كس نمي تواند مبالغي بيش از حد تعيين شده را بدون اجازه مدير خود جابجا كند. فرض برنامه نويسان در اينجا ناقص است چون در نظر نگرفته اند كه ممكن است فردي سعي كند تا مبالغ منفي را جابجا كند. در اين صورت فرد نيازي به تأييد مدير خود ندارد زيرا هر مقدار منفي كمتر از Trshold است. جالب است كه در همين برنامه تابع مربوط به نقل و انتقالات بانكي مبالغ منفي را پذيرفته و آن را به عنوان انتقال معكوس در نظر مي گيرد. براي مثال در صورتي كه قرار است مبلغ X از حساب A به حساب B منتقل شود، مي توان مبلغ –X را از حساب B به A منتقل كرد. با اين حساب كاربر خرابكار مي تواند هر مقداري را كه بخواهد در قالب عددي منفي در بين حساب ها جابجا كند!
بسياري از برنامه هاي كاربردي از محدوديت هاي عددي در برنامه هاي خود استفاده مي كنند. براي مثال مي توان به موارد زير اشاره كرد:

  • يك برنامه كاربردي متعلق به يك فروشگاه ممكن است مانع از فروش كالا بيش از مقدار موجود در انبار شود.
  • يك برنامه كاربردي متعلق به بانك لازم است از برداشت پول بيش از مقدار موجود در حساب جلوگيري به عمل آورد.
  • يك برنامه كاربردي متعلق به شركت بيمه ممكن است درخواست ها را بر مبناي حدي از تعداد سال ها تنظيم كند.

مي توان مثال هاي مشابه زياد ديگري را نيز مطرح كرد. در صورتي كه يك كاربر خرابكار بتواند به نوعي در شرط هاي مذكور تقلب كند، ممكن است منجر به حملات مختلف و يا نشت اطلاعات شود. لذا برنامه نويسان لازم است در به كارگيري محدوديت هاي عددي نهايت دقت را به كار برند.

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

شرايط رقابتي در ورود به سيستم
اين مثال مربوط به يك برنامه كاربردي تحت وب متعلق به يك بانك است. در اين برنامه راهكارهاي متعددي براي ورود و تأييد هويت افراد ديده شده است. از ديدگاه طراحان و برنامه نويسان اين برنامه، افراد خرابكار به هيچ وجه نمي توانند وارد اين سيستم شوند. با وجودي كه آنها تمام نكات امنيتي و راهكارهاي موجود براي تأييد هويت امن را رعايت كرده بودند، اما گاهي اوقات مواجه با اتفاقي عجيب مي شدند؛ زماني كه كاربري وارد سيستم مي شد مي توانست به كنترل كامل حساب كاربري ديگري نيز دسترسي پيدا كند. ظاهراً اين اتفاق به صورت تصادفي رخ مي داد و حتي دسترسي به حساب كاربران ديگر نيز به صورت تصادفي بود. بعد از تحقيقات بسيار مشخص شد، زماني كه دو كاربر به صورت تقريباً همزمان وارد سيستم مي شوند، كاربري كه اول وارد شده است مي تواند به حساب كاربري فردي كه بلافاصله بعد از او وارد سيستم شده است دسترسي پيدا كند. در بررسي كد برنامه معلوم گشت كه برنامه براي هر فرد كه وارد سيستم مي شود بعد از گذشتن از مراحل ورود به سيستم (login) يك كد تأييد هويت ايجاد مي كند كه با استفاده از آن كنترل حساب كاربري تا زمان خروج از سيستم (logout) در اختيار وي قرار مي گيرد. اشتباه آنها در اين بود كه از يك متغير استاتيك براي نگهداري اين كد استفاده كرده بودند و در مواقع نادري به علت استاتيك بودن متغير، همان كدي كه به شخص بعدي تخصيص داده شده بود به فرد قبلي نيز انتقال پيدا مي كرد و وي مي توانست به هر دو حساب به صورت همزمان دسترسي پيدا كند!
آسيب پذيري هاي موجود در منطق برنامه تنها نوعي از آسيب پذيري ها هستند كه به صورت كامل قابل اجتناب نيستند، اما راهكارهايي وجود دارد كه بتوان آنها را به حداقل رساند. در مقاله بعدي در مورد راهكارهاي اجتناب از نقص هاي امنيتي در منطق برنامه، صحبت خواهيم كرد.

برچسب‌ها