چند سالیه که باب شده همه رسانههای تصویری و اینترنتی برای مسابقات ورزشی، بخش شرط بندی و پیشبینی نتایج رو میگذارند. امسال فروشگاه اینترنتی دیجیکالا هم سایتی برای پیشبینی نتایج یورو ۲۰۱۶ رونمایی کرد. ده روز پیش بود که یکی از دوستان در توییتر به برخی پیشبینیها مشکوک شد و پیشنهاد داد سایت رو بررسی کنم.
در همون بررسی اولیه متوجه شدم که اطلاعات ارسالی کاربر به سرور بیش از حد نیازه و در هر پیشبینی، علاوه بر شناسه بازی و کد پیشبینی (برنده، مساوی و یا بازنده)، ایمیل کاربر و کد کاربر هم ارسال میشه. دریافت إیش از حد اطلاعات از کاربر چند مساله ایجاد میکنه.
ضعف امنیتی اول: ورودیهای خطرناک
یکی از اصول اولیه در حفظ امنیت اینه که به ورودیها اعتماد نکنیم. درسته که قراره کد بازی یک عدد دو رقمی باشه، اما اگر کاربر یک دستور سمت سرور فرستاد که همه اطلاعات رو نشونم بده چی؟ سرور باید دستور رو اجرا کنه؟ اگر تمهیدی براش نیندیشیده باشیم، این اتفاق میافته. این مورد رو روی ورودیهای دیجیکالا تست کردم و شواهد نشون میده که اعتبارسنجی، پاکسازی و حذف کاراکترهای مشکوک به درستی انجام نمیشه.
در فیلم زیر میبینیند که به صورت دستی پیشبینی بازی شماره ۲۲ رو سمت سرور فرستادم که نپذیرفت چون قبلا این پیشبینی انجام شده بود. پیشبینی بازی ۲۳ رو پذیرفت و پیشبینی بازی ۲۴ ضرب در ۱ رو هم پذیرفت ولی قاعدتا نباید این اتفاق میافتاد. چون برای عمل ریاضی + خطا میداد پس پاکسازی انجام نمیشه.
همچنین کاراکتر ‘ هم برای شماره بازی بعد در کنار عدد ۱۹ ارسال کردم و همونطور که در تصویر میبینید به جای حذف کاراکتری که بدیهیست نباید توی این ورودی ارسال بشه، برای اجرا به کدهای php سپرده میشه. پیام خطای ناشی از این مشکل رو میبینیم.
من بررسی این مشکل رو ادامه ندادم و برای تزریق کد سمت سرور اقدام نکردم و نمیتونم با اطمینان بگم این ضعف امنیتی در بررسی ورودیها، منجر به نفوذ و یا تغییر پایگاه داده میشه یا نه. کسی که قصد تخریب داشته باشه، از این مرحله کارش شروع میشه.
ضعف امنیتی دوم: مشکل در سطح دسترسی
پیش از شروع کار برنامهنویسی، باید ساختار کلی برنامه تعیین بشه و یکی از مهمترین نکتهها، تعیین سطح دسترسی کاربرها و کنترل درخواستها بر این اساسه. وقتی نوع ارسال پیشبینیها به سرور رو مشاهده کردم، متوجه شدم علاوه بر استفاده از کوکیها که نشوندهنده ورود موفق یک کاربره، اطلاعات دیگهای مرتبط به کاربر ارسال میشه از جمله ایمیل و کد کاربری.
به نظرم رسید که این ارسال دوباره کد کاربر میتونه بین مسیر دستکاری بشه. درسته که ما توی فرم صفحه، کد کاربری که لاگین کرده رو قرار دادیم اما همونطور که گفتم، هیچوقت نباید به اطلاعاتی که از سمت کاربر دریافت میکنیم اعتماد کنیم. از دوست خوبم بنیامین، نویسنده وبلاگ سیانوژن، خواستم که دو تا اکانت بسازه تا بتونم این مورد رو چک کنم. متاسفانه حدسی که میزدم درست بود و اطلاعات ارسالی نه از نظر سطح دسترسی چک میشد و نه از نظر زمانی کنترل میشد.
در فیلم زیر خواهید دید که ابتدا درخواست ارسالی برای پیشبینی نتیجه بازی آلبانی و رومانی رو به دست میارم و ذخیره میکنم. بعد با اکانت بنیامین وارد میشم، یک پیشبینی ارسال میکنم و کوکیهای این نشست رو ذخیره میکنم. برای تست ابتدا با کوکیها و ایمیل بنیامین و کد کاربری بنیامین، پیشبینی بازی فرانسه و سوییس رو ارسال کردم. در فیلم خواهید دید که پیام failed دریافت کردم چون بنیامین قبلا این بازی رو پیشبینی کرده بود. سپس کد کاربری خودم رو در درخواست ارسالی گذاشتم و در واقع با اکانت بنیامین برای خودم یک بازی رو پیشبینی کردم و با موفقیت انجام شد. برای اطمینان به اکانت خودم لاگین کردم و خواهید دید که پیشبینی که بنیامین برای من انجام داده بود، به اکانت اضافه شده.
تا اینجا دیدیم که شناسه کاربری به درستی چک نمیشه و میتونیم هر مقدار غیر منطقی (مقدار مربوط به اکانت دیگران) رو ثبت کنیم. اینجوری هر کسی میتونه از پیش همه بازیهای بعدی رو برای همه کاربرها پیشبینی کنه.
ورودی دیگه، شناسه بازی است. منطق پیشبینی میگه اکانت جدید نباید بتونه بازیهای قبلی رو پیشبینی کنه. من درخواستی رو برای بازی شماره یک ارسال کردم و در فیلم میبینید که پذیرفته میشه و یک بازی قدیمی به لیست پیشبینیهای من اضافه شد.
نکته:
این فیلمها بلافاصله بعد ضبط شدن برای دیجیکالا ارسال شد تا مشکل رو برطرف کنند. ده روز هم فاصله گذاشتم برای عمومی کردن ضعف امنیتی تا کاربران به خطر نیافتند. همچنین تستها رو با اکانت شخصی انجام دادم که اکانت کسی آسیب نبینه. هیچگونه تست مخربی رو روی سایت فعال انجام ندادم و با توجه به مشکلاتی که میبینم، به دیجیکالا توصیه میکنم تست نفوذ کامل روی نسخه تست web application انجام بدن.
میشه حدس زد که کار با عجله طراحی اجرا شده. احتمالا برنامهنویسهای این کار، زمان زیادی نداشتند که این مشکلات رو توی خروجی نهایی برطرف کنند. پیشنهاد میکنم تیم برنامهنویسی، مخصوصا در شرایطی که زمانی کمی دارند، تست رو از مراحل ابتدایی توی پروژه در نظر بگیرند.
خوشبختانه تیم دیجیکالا بلافاصله بعد از اعلام من، اصلاح رو شروع کردند. بعد از ایمیلی که برای دیجیکالا فرستادم، دیدم دوست دیگری هم مشکلی رو در توییتر اعلام کرده بود. با توجه به عمومی شدن مشکلات این سایت، امیدوار بودم در این فاصله زمانی اطلاعیه برای کاربران ارسال بشه که من تا زمان نوشتن این پست، خبری از دیجیکالا ندیدم. گویا روزهای گذشته هنگام ورود به سایت، این مورد به کاربران اعلام شده بود.