۱۰ اشتباه امنیتی که نباید در وب اپلیکیشن های خود مرتکب شوید | راهنمای کاربردی
شما به عنوان یک توسعهدهنده در خط مقدم دفاع در برابر افشای دادهها قرار دارید. بنابراین باید بدانید که به دنبال چه هستید و مسئولیت رعایت قوانین مناسب از سوی کاربران بر عهده شما است. خوشبختانه یک سازمان وجود دارد که به طور خاص برای ارائه راهنماهای بهروز در خصوص شیوه تأمین امنیت وباپلیکیشنها فعالیت میکند. شما به عنوان یک توسعهدهنده وب باید با ده اصل مهم OWASP آشنا باشید تا این 10 اشتباه امنیتی را در اپلیکیشن های خود مرتکب نشوید.
«پروژه باز امنیت وباپلیکیشنها» که به اختصار OWASP نامیده میشود یک سازمان غیرانتفاعی است که به منظور ارتقای امنیت در وب تأسیس شده است. این سازمان غیرانتفاعی پژوهشهای زیادی در خصوص تهدیدها و آسیبهایی که در برابر اپلیکیشنهای مدرن وجود دارد، انجام داده است.
بر اساس نظر کارشناسان استفاده از 10 توصیه مهم OWASP احتمالاً مؤثرترین گام در زمینه تغییر فرهنگ توسعه نرمافزار درون سازمان به سمت تولید کدهای با امنیت بالاتر محسوب میشود.
رعایت توصیههای OWASP یک استاندارد مهم برای امنیت به حساب میآید. اگر یک توسعهدهنده وب هستید، باید در مورد OWASP اطلاع داشته و توصیههای برتر آنها را درک کنید. در این مقاله با مهمترین خطراتی که وباپلیکیشنها را تهدید میکنند آشنا خواهیم شد.
تزریق
وبسایتها باید دادههایی را از سوی کاربران دریافت کنند، چون در غیر این صورت فایده چندانی نخواهند داشت. با این حال پیش از آن که کاری روی این داده انجام دهید، مثلاً پیش از مرتبسازی، اجرای کد روی دادهها و یا گشتن به دنبال چیزی، باید مطمئن شوید که دادهها پاک هستند و کاراکترهای خاص escape شدهاند.
اگر این کار را انجام ندهید، حملهکنندگان میتوانند به صورت بالقوه کد مورد نظر خود را روی سرورهای شما اجرا کنند. بهترین روش برای جلوگیری از بروز تزریق، استفاده از کتابخانهای است که دادههای ورودی کاربر را هر بار و به محض این که دادهها به سرور میرسند، پاکسازی میکند. هر زبان برنامهنویسی برای وب، ابزارها و کتابخانههای خاصی برای اجرای این پاکسازی ورودیها ارائه کرده است.
این نخستین ریسک امنیتی است، زیرا قدرت زیادی دارد و به مهاجم امکان میدهد که کد دلخواه خود را اجرا کند. همچنین علیرغم این که دههها است شناخته شده است، همچنان یک مشکل شایع محسوب میشود.
درز اطلاعات احراز هویت
زمانی که یک مهاجم بتواند به عنوان فرد دیگری وارد سیستم شود، بدیهی است با یک مشکل مواجه میشویم. این دسته از ریسکها شامل مسائل بالقوه زیادی است:
- ذخیرهسازی رمزهای عبور به صورت «متن ساده» (plaintext) در پایگاه داده که هرگز (مطلقاً هرگز) نباید انجام گیرد، موجب میشود که پایگاه داده به مخاطره بیفتد.
- ذخیره توکنهای سِشِن (session) در مکانهای ناامن به مهاجمان امکان میدهد که از این توکن برای به دست آوردن اطلاعات احراز هویت استفاده کنند.
- ایجاد امکان انتخاب رمزهای عبور ساده یا ضعیف برای کاربران موجب میشود که مهاجمان بتوانند آنها را به سادگی حدس بزنند.
- عدم تعیین تاریخ انقضا برای توکنهای سشن یا API به این معنی است که یک توکن، تنها کافی است یک بار درز کند تا مهاجم برای همیشه بتواند از آن سوءاستفاده کند.
- ارسال اطلاعات مختلف و قابل شناسایی بر مبنای درخواستهای ناموفق یک کار مخاطرهآمیز است. برای نمونه این که در پاسخ یک اقدام به لاگین ناموفق پیامی با مضمون «چنین نام کاربری وجود ندارد» نمایش دهید، به این معنی است که مهاجم میتواند این مورد را از فهرست حدسهای خود کنار بگذارد و سریعتر به دنبال یک نام کاربری موجود بگردد که پاسخ متفاوتی بازگشت میدهد. در این موارد بهتر است پیام «اطلاعات نامعتبر» (Invalid credentials) را نمایش دهید.
روشهای فوق از بروز برخی از مشکلات مرتبط با اطلاعات احراز هویت جلوگیری میکنند. بر اساس گزارش OWASP اجرای اقدامات زیر در این زمینه مفید خواهد بود:
- هر جا که ممکن است از «احراز هویت چند عاملی» (multi-factor authentication) استفاده کنید تا از بروز حملههای رباتی، جعل اطلاعات هویتی، «حملههای کور» (brute force) و استفاده مجدد از احراز هویت سرقتی جلوگیری نمایید.
- در زمان توزیع نرمافزارها از اطلاعت احراز هویت پیشفرض به خصوص برای کاربران admin خودداری کنید.
- ضعیف بودن رمزهای عبور مثلاً اعتبارسنجی رمزهای عبور جدید یا تغییر یافته را در برابر لیستی از 10،000 رمزعبور بد بررسی کرده و الزام به استفاده از دست کم 8 کاراکتر را در رمز عبور داشته باشید.
- از وجود استحکامات امنیتی در بخشهای ثبت نام، بازیابی اطلاعات احراز هویت و مسیرهای API در برابر حملههای شمارش اکانت و با بهرهگیری از پیامهای خروجی مطمئن شوید.
- تلاشهای ورود ناموفق را محدود کرده و یا تأخیر آن را افزایش دهید. همه موارد شکست را لاگ کرده و در مواردی ثبت اطلاعات احراز هویت، حملههای کور یا دیگر انواع حمله را شناسایی کردید، به مدیران اطلاع دهید.
- از یک ابزار مدیریت سشن سمت سرور، امن و داخلی استفاده کنید که یک ID سشن تصادفی جدید با آنتروپی بالا پس از لاگین ایجاد میکند. ID-های سشن نباید در URL باشند و باید به صورت امنی ذخیره شوند و پس از خروج کاربر از حساب، یا بیکار ماندن و انقضای زمانی اعتبار خود را از دست بدهند.
افشای دادههای حساس
در طی سالهای اخیر، این نوع حمله، رایجترین گزینه بوده است. همه چیز رفتهرفته پیچیدهتر میشود، زیرا مهاجمان میتوانند از انواع مختلفی از سناریوهای «فرد میانی» (man-in-the middle) برای سرقت دادههایی استفاده کنند که در حال عبور روی شبکه هستند و یا موقتاً به صورت «متن ساده» ذخیره شدهاند.
این مهاجمان میتوانند اشکال مختلفی داشته باشند، اما روشهای رایج حمله برای سرقت اطلاعات به صورت زیر هستند:
- داونگرید کردن اتصال از HTTPS به HTTP برای رمزگشایی دادهها در زمان ارسال.
- کرک کردن طرح یک رمزنگاری ضعیف که برای ذخیره با انتقال دادهها مورد استفاده قرار میگیرد.
- پیش-هشسازی رمزهای عبور رایج با استفاده از طرحهای رمزنگاری ساده و بدون salt و سپس انطباق دادن آنها با جداول کاربری به سرقت رفته.
- استفاده از تزریق SQL برای این که موتور پایگاه داده، دادهها را به صورت متن ساده واکشی کند که رمزنگاری نشدهاند.
برای جلوگیری از بروز این مشکلات باید اقدامات زیر را انجام دهید:
- همه دادههای حساس باید با یک الگوریتم رمزنگاری مدرن رمزنگاری شوند.
- اگر ضرورتی مطلق برای ذخیرهسازی برخی دادهها وجود ندارد، آنها را پاک کنید. اگر شما چیزی را ذخیره نکنید، سارقان نیز نمیتوانند آن را بدزدند.
- رمزهای عبور را با استفاده از تابعهای هشسازی قوی تطبیقی و دارای salt یا یک عامل کاری (عامل تأخیر) مانند Argon2، scrypt، bcrypt یا PBKDF2 رمزنگاری کنید.
- مطمئن شوید که کوکیهای سشن و دیگر دادههای حساس مرورگر تنها روی HTTPS ارسال میشوند و جاوا اسکریپت سمت کلاینت به آنها دسترسی ندارد.
ماهیتهای اکسترنال XML
حملههای XEE به مهاجم امکان میدهند که کد شما در زمانی که یک فایل XML را به اپلیکیشن آپلود میکنید، به صورت یک URL ارزیابی کند.
این نوع از حملهها به طور خاص شایع هستند و روی اپلیکیشنهای قدیمی با وابستگیهایی که بهروز نشدهاند و در برابر حملههای XEE محافظت نمیشوند موفق خواهند بود. سادهترین روش برای جلوگیری از بروز این نوع حمله آن است که از XML استفاده نکنید. به جای آن یک فرمت داده صریحتر مانند JSON یا YAML را مورد استفاده قرار دهید.
اگر مجبور به استفاده از XML هستید، مطمئن شوید که parser-ها، پردازشگرها و وابستگیها بهروز هستند. ابزارهای آنالیز سورس کد به شناسایی مشکلات در اپلیکیشنهای موجود کمک میکنند.
از کار افتادن کنترل دسترسی
این دسته از حملهها مشابه دسته دوم حملات یعنی از کار افتادن احراز هویت هستند که پیشتر بررسی کردیم، اما زمانی استفاده میشوند که مهاجم بتواند به دادهای حساس بدون ورود به عنوان کاربر صحیح دسترسی پیدا کند. برای نمونه فرض کنید یک مهاجم وارد وبسایت شما میشود و به صفحه تاریخچه صورتحساب که URL مانند زیر دارد میرود:
mysite.com/users/1809/billing/history
میتوان با اطمینان حدس زد که بخش 1809 در URL صفحه همان ID کاربر است. اگر مهاجم بتواند این ID را تغییر دهد و دادههای صورتحساب افراد دیگر را ببیند، در این صورت شما با حمله از کار افتادن کنترل دسترسی مواجه شدهاید.
به صورت مشابه، مهاجمان میتوانند ID-های دیگران، توکنها یا اطلاعات احراز هویت را دستکاری کنند تا URL-های مسدودشده را ببینند یا دسترسیهای سطح مدیر را به دست آورند. چکلیست جلوگیری از بروز این نوع حمله به صورت زیر است:
- به طور پیشفرض همه درخواستهای وب و نقاط انتهایی API را انکار کنید تا فرایند احراز هویت استاندارد و پیشفرضی در سراسر اپلیکیشن به وجود آید.
- دسترسی برای ایجاد، خواندن، بهروزرسانی و حذف روی مدلهای دادهها باید همواره مختص کاربر باشد و به وسیله مجوزهای مدل صریح مدیریت شود.
- امکان لیست کردن دایرکتوری وبسرور را غیر فعال کرده و مطمئن شوید که متادیتای فایل و فایلهای پشتیبان در ریشههای وب حضور ندارند.
- شکستهای کنترل دسترسی را لاگ کرده و در موارد مقتضی مانند تکرار شکستها را به مدیر اطلاع دهید.
- برای API و URL-ها یک محدودیت نرخ تعیین کرده و از دستکاریهایی که از سوی ابزارهای خودکار تولید میشوند جلوگیری کنید.
ریزپیکربندی امنیتی
مهم نیست سرور یا فریمورک سمت کلاینت شما چه قدر امن است، اگر تنظیمات امنیتی به درستی پیکربندی نشده باشند، این مسئله برای شما امنیتی ایجاد نمیکند. برای نمونه بسیاری از فریمورکها دارای تنظیمات دیباگ هستند که در زمان توسعه مفید هستند، اما زمانی که اپلیکیشن در محیط پروداکشن منتشر میشود، خطرناک خواهند بود.
مشکلات دیگر در این زمینه به شرح زیر هستند:
- رها کردن حسابهای پیشفرض به صورت فعال و/یا تغییر ندادن رمزهای عبور پیشفرض آنها.
- داشتن پیامهای خطایی که ردهای پشته یا دیگر اطلاعات را در مورد پیکربندی افشا میکنند.
- استفاده از فریمورکها یا کتابخانههای تاریخ-گذشته بدون نصب جدیدترین وصلههای امنیتی.
- رها کردن متغیرهای محیطی یا دیگر کلیدهای امن در فایلهای پیکربندی یا کنترل سورس که دسترسی عمومی دارند.
خوشبختانه رفع این موارد کار آسانی است. در این موارد باید از نسخه بهروز شدهای از فریمورکها و کتابخانهها استفاده کنید. سپس در مورد رویههای مناسب امنیتی برای پیکربندی اپلیکیشن برای محیط پروداکشن کسب اطلاع نمایید. به علاوه مطمئن شوید که فرایند توزیع به محیط پروداکشن همواره به روشی قابل پیشبینی شامل این گامهای مستحکمسازی امنیتی است.
اسکریپتنویسی بین سایتی (XSS)
این یک نوع حمله است که در طی سالهای اخیر شیوع بیشتری یافته است چون جاوا اسکریپت سمت کلاینت رواج بیشتری پیدا کرده است.
این جمله اساساً شامل اجرای جاوا اسکریپت و HTML خرابکارانه در مرورگر کاربر است. با این که به نظر میرسد این کد از یک سایت معتبر میآید، اما در واقع از یک منبع خرابکارانه نشات یافته است. برای نمونه اگر یک سایت که به آن اعتماد دارید، یک popup مانند زیر باز کند، آیا آن را پر میکنید؟
با این که ممکن است این صفحه قابل وثوق باشد، اما این امکان نیز وجود دارد که از سوی یک مهاجم متقلب ارائه شده باشد که طراحی و قابلیتهای سایت هدف را تقلید کرده است. حملههای خرابکارانه XSS سه گونه کلی به شرح زیر دارند:
- XSS بازتابی: اپلیکیشن یا API شامل ورودی کاربر اعتبارزدایی شده یا escape نشده به عنوان بخشی از خروجی HTML است.
- XSS ذخیره شده: اپلیکیشن یا API ورودیهای پاکسازی نشده کاربر را ذخیره میکند که در زمانهای بعدی از سوی کاربر دیگر یا یک مدیر دیده میشوند.
- DOM XSS: فریمورکهای جاوا اسکریپت، اپلیکیشنهای تکصفحهای و API-هایی که به صورت دینامیک شامل دادههای قابل کنترل از سوی مهاجم هستند در برابر دستکاری DOM آسیبپذیرند.
برای جلوگیری از این نوع حملهها باید اقدامات زیر را انجام دهید:
- از فریمورکهای بهروز شدهای که در برابر XSS محافظت شدهاند، از قبیل Django، Rails، Spring، React،Angular و یا غالب فریمورکهای عمده دیگر که شامل این حفاظت هستند، استفاده کنید.
- هرگز دادههای غیر قابل اعتماد را درون یک اسکریپت، کامنت HTML، تگها، خصوصیتهای تگ یا مستقیماً در CSS قرار ندهید.
- هر گونه داده غیر قابل اعتماد که در صفحه قرار میگیرد ار به صورت زیر escape کنید:
& --> & < --> < > --> > " --> " ' --> ' / --> /