# برنامه نویسی با محصولات مایکروسافت > برنامه نویسی مبتنی بر Microsoft .Net Framework > مقالات مرتبط با Microsoft .Net Framework >  روش های محافظت و موارد رعایت اصول امنیتی در برنامه های ASP.NET

## Behrouz_Rad

*
توجه: کلیه ی حقوق مطالب این تاپیک متعلق به سایت www.barnamenevis.org می باشد. استفاده از مطالب این تاپیک به هر شکل، منوط به ذکر نام منبع است.
*
در این تاپیک به "روش های محافظت از برنامه های ASP.NET" و "رعایت اصول امنیتی در برنامه های ASP.NET" پرداخته میشه.

-----------------------------------

امنیت چیست؟
تعریف اول: امنیت وضعیتی رو تشریح می کنه که باعث تعامل صحیح کاربر با برنامه میشه.
تعریف دوم: مجموعه عملیاتی که انجام میگیره تا عاملی رو در برابر اقدامات متخاصمانه حفظ کنه.

در بالاترین سطح برنامه های وب، امنیت دو مقوله داره:
1) امنیتی که توسط برنامه نویس به وجود میاد.
2) امنیتی که توسط Host به وجود میاد.

مورد اول دست شما هست و می تونید اون رو کنترل کنید.
مورد دوم دست شما نیست و کنترلی بر اون ندارید. پس هاستی رو انتخاب کنید که تیم فنی خوبی داره و همیشه سیستمشون رو با Patch ها و برنامه های بروز شده حفظ می کنند.

در این تاپیک ما در مورد "روش های حفظ امنیت توسط برنامه نویس" صحبت می کنیم.

سرچشمه ی امنیت از کد نشات میگیره.
یک کد خوب امنیت کافی رو به وجود میاره.
یک کد بد یا اصطلاحا Dirty Code، بلای جان برنامه نویس محسوب میشه.
پس زیبا کد بنویسید تا گام اول رو صحیح بردارید.

ابزار FxCop توسط مایکروسافت برای برنامه نویسان NET. عرضه شده تا کدهاشون رو مطابق با استاندارد کدنویسی تعریف شده توسط NET. بنویسند.

راهنمای کدنویسی NET.

ابزار FxCop

----------


## Behrouz_Rad

*مدیریت اطلاعات مهم:*

اطلاعات مهم مثل: نام کاربری، کلمه ی عبور، Connection String، اطلاعات لایسنس و ... هستند.
این مهمه که شما این اطلاعات رو در کجا نگهداری کنید.
مکان نگهداری این اطلاعات اصل ثابتی نیست و بیشتر جنبه ی پیشنهادی داره. معیارهای مختلفی در این انتخاب سهیم هستند.

1) برخی اطلاعات جنبه ی حیاتی دارند و حتی خود برنامه نویس هم بعد از انتشار برنامه نباید از اونها مطلع باشه. مثل کلمه ی عبور حساب بانکی یک فرد. در این حالت این کلمه ی عبور باید با یک الگوریتم Hash به رمز در بیاد و در دیتابیس ذخیره بشه.
الگوریتم های Hash برگشت پذیر نیستند مثل MD5.
بهتر هست که این دسته از اطلاعات با استفاده از یک بستر انتقال امن همانند SSL منتقل بشن.

2) برخی اطلاعات مهم هستند اما نیازی به رمزنگاری ندارند. مثل Connection String.
در این حالت برنامه نویس مطمئن هست که فقط خودش می تونه به این اطلاعات دسترسی داشته باشه نه شخص دیگری.
این اطلاعات بهتره در Web.Config ذخیره بشن.
سوال: در NET 2.0. امکان رمزنگاری (Encryption) محتویات فایل Web.Config وجود داره. آیا پیشنهاد میشه که از این امکان استفاده کنیم؟
پاسخ: نه برای هر نوع اطلاعاتی. به نظر من رمزنگاری Connection String کار بیهوده ای محسوب میشه. هیچ کس به جز شما و هاست به Web.Config دسترسی نداره.
نتیجه گیری اخلاقی: اگر فکر می کنید که احتمال ریختن سقف خونتون وجود داره، هیچ وقت در خونه نمونید! در غیر اینصورت به سقف خونتون اطمینان کنید.
یکی از مزایای مهم قرار دادن Connection String شما در Web.Config، استفاده از قابلیت Connection Pooling هست.
نتیجه گیری: Connection String رو همیشه بدون رمزنگاری در Web.Config قرار بدید.

3) برخی اطلاعات با دیگران به اشتراک گذاشته میشن اما اشتراک اونها شرط خاصی داره.
به عنوان مثال: لایسنس کامپوننتی که باید همراه با اون وجود داشته باشه.
این اطلاعات معمولا در فایلی با پسوند lic در کنار کامپوننت قرار دارند و مثلا می تونند حاوی Key تولید کننده ی سریال نامبر کامپوننت برای بررسی صحت سریال وارد شده توسط خریدار باشند.
این اطلاعات فقط باید توسط برنامه نویس قابل دسترسی باشند نه توسط فردی که اطلاعات با اون به اشتراک گذاشته شده.
این اطلاعات باید توسط یک الگوریتم، Code شوند. مثلا الگوریتم های کد کردن 64 یا 128 بیتی و یا از الگوریتم های متقارن همانند DES برای رمزنگاری اونها استفاده بشه.

نتیجه گیری پایانی: Encryption و Hash و Code، سه اصطلاح مختلف هستند و کاربرد مجزایی دارند.

----------


## Behrouz_Rad

*نکاتی در باب رمزنگاری داده ها:*

سعی کنید تا حد ممکن از الگوریتم های رمزنگاری NET. استفاده کنید و از استفاده از الگوریتم هایی که خودتون اختراع کردید بپرهیزید.
دات نت تقریبا به طور کامل تمام الگوریتم های معروف و مورد نیاز شما رو برای رمزنگاری فراهم می کنه.

1) الگوریتم Rijndael برای رمزنگاری متقارن خوب هست.
2) الگوریتم 3DES برای رمزنگاری داده هایی که مدت زیادی وجود دارند مناسب هست.
3) الگوریتم های RC2 و DES برای رمزنگاری داده هایی که عمر و ماندگاری کوتاه تری دارند مناسبند.
4) در رمزنگاری های متقارن و نامتقارن همیشه از کلیدهایی با اندازه ی طولانی استفاده کنید. طبق تحقیقاتی که چند وقت پیش شرکت مک آفی منتشر کرد، مشخص شد که شکستن کلیدهای طولانی اما ساده، بیشتر از کلیدهای پیچیده اما کوتاه زمان بر هست!
5) برای Hashing، الگوریتم های MD5 و SHA1 مناسب و کافی هستند.
6) اگر در رمزنگاری نیاز به تولید یک عدد تصادفی داشتید، از کلاس RNGCryptoServiceProvider استفاده کنید. این کلاس کاملا با الگوریتم ها رمزنگاری دات نت منطبق هست و اعداد کاملا تصادفی تولید می کنه. به کلاس Random نمیشه زیاد اعتماد کرد.

----------


## Behrouz_Rad

*استفاده از تصاویر امنیتی در هنگام ورود اطلاعات:*

یک تصویر امنیتی از تعدادی حرف و عدد در کنار هم تشکیل شده که تنها انسان ها قادر به خواندن اونها هستند و در جایی که نیاز به ورود اطلاعات هست استفاده میشه.
کاربرد تصاویر امنیتی در جلوگیری از ارسال مداوم داده ها به سرور هست.
حملاتی که به اشغال شدن سرور منجر میشن به حملات DOS معروف هستند.
نوشتن برنامه ای که در فواصل زمانی کوتاه، مدام داده هایی رو از طریق برنامه ی شما به سرور ارسال کنه بسیار راحت هست. بدین دلیل همیشه در صفحاتی که برای عموم قابل مشاهده هست (و نه خواص) حتما از تصاویر امنیتی استفاده کنید.

آموزش ساخت تصاویر امنیتی

----------


## Behrouz_Rad

*محافظت از برنامه در برابر SQL Injection:*

در مورد SQL Injection زیاد شنیدید.
به طور خلاصه، به تزریق کدهای SQL از طریق برنامه، SQL Injection گفته میشه.
شاید بشه گفت که خطرناکترین نوع حمله ای که می تونه به یک برنامه صورت بگیره SQL Injection هست که متاسفانه بسیاری از افراد اون رو نادیده میگیرن و نسبت به اون بی توجه هستن.
عدم توجه به توانایی تزریق SQL به برنامه، عملا دیتابیس رو در اختیار فرد مهاجم قرار میده و می تونه تمام هست و نیستی شما رو بر باد بده!
راه جلوگیری از SQL Injection، استفاده از پارامترها برای ارسال مقادیر به دیتابیس هست.
پارامترها می تونن همراه با Stored Procedure استفاده بشن و در صورت عدم استفاده از Stored Procedure ها، با نوشتن مستقیم دستورات SQL در کد برنامه نیز قابل استفاده هستند.
اون چیزی که مهم هست اینه که در هر شرایطی از پارامترها برای پاس دادن مقادیر ورودی به Command استفاده کنید.

برخی افراد برای مقابله با SQL Injection، برخی کلمات کلیدی SQL، نظیر DELETE، UPDATE، DROP و ... رو در رشته ی ورودی فیلتر می کنند.
این عمل ساده لوحانه، صرف نظر از ایجاد محدودیت برای برخی کلمات در ورودی و Poor Coding، نکته ای رو از دید این افراد دور نگه داشته و اون این هست که:
*هر کاراکتر یک کد hexadecimal داره که می تونه به جای کاراکتر اصلی در ورودی قرار بگیره و بدین طریق میشه به راحتی کلمه ی محدود شده رو دور زد!
به عنوان مثال، معادل کلمه ی DROP، عبارت 0x440x520x4F0x50 هست!*

از مطلب اخیر سوء استفاده نکنید ;)

پ.ن: از متد HexEscape کلاس Uri می تونید برای به دست آوردن کد HEX کاراکتر استفاده کنید.

----------


## Behrouz_Rad

*مدیریت صحیح خطاها:*

1) از روش های مدیریت خطای ساخت یافته (Try Catch Finally) برای هندل خطاهای برنامه استفاده کنید.

2) پس از تشخیص خطا بلافاصله در جهت رفع اون اقدام کنید و این کار رو به تاخیر نیندازید.

3) جزئیات خطا رو در جایی ذخیره کنید. این مکان تنها باید توسط شما قابل دسترسی باشد.

4) هیچگاه جزئیات خطا رو به کاربر نشان ندید. در عوض، پیغام های کلی رو که بیانگر بروز خطاست نمایش بدید.

5) قبل از انتشار برنامه، مقدار خاصیت mode تگ customErrors رو در Web.Config همیشه بر روی On یا RemoteOnly تنظیم کنید تا جزئیات خطاهای هندل نشده به کاربر نشان داده نشن.

6) در بند قبل، حتما صفحه ای رو برای برنامتون ایجاد کنید تا در صورت وقوع یک خطای هندل نشده، کاربر به این صفحه هدایت بشه. این صفحه رو با تنظیم مقدار خاصیت defaultRedirect تگ customErrors به نام این صفحه به برنامه معرفی کنید.

7) نام صفحه ای که موجب وقوع خطا شده در یک Query String با نام aspxerrorpath قرار می گیره و به صفحه ای که در بند قبل اشاره شد پاس داده میشه. از طریق بازیابی مقدار این Query String می تونید متوجه بشید که کدام صفحه موجب بروز خطا شده.

8) برخی خطاها ارتباطی با کدهای برنامه ندارند و یک عامل خارجی باعث رخ دادن اونها میشه. مثل تایپ نام صفحه ای که وجود نداره در Address bar توسط کاربر که باعث نمایش پیغام Page Not Found (کد 404) در مرورگر میشه. این نوع خطاها رو میشه به دو طریق هندل کرد.
یا از طریق زیر تگ error که یکی از زیر تگ های customErrors در Web.Config هست و یا از طریق هندل کردن روال Application_Error در فایل Global.asax.
به عنوان مثال، برای هندل کردن این مورد که صفحه ی مورد نظر وجود نداره، میشه به شکل ذیل در Web.Config عمل کرد:

<customErrors mode="On" defaultRedirect="myCustomErrorPage.htm">
   <error statusCode="404" redirect="myPageNotFound.htm"/>
</customErrors>

در دستورات فوق، در صورتی که کاربر نام صفحه ای رو تایپ کنه که وجود نداره، به صفحه ای با نام myPageNotFound.htm هدایت میشه.
برای هندل کردن خطا در روال Application_Error نیز متد GetLastError کلاس Server رو فراخوانی کنید.
نکته ی مهم: در این حالت، در آخرین خط این روال، متد ClearError کلاس Server رو حتما فراخوانی کنید تا Stack از خطا خالی بشه و خطا مجددا رخ نده.

9) قبل از انتشار برنامه، trace رو با تنظیم خاصیت enabled تگ trace در Web.Config به false غیر فعال کنید.

----------


## anubis_ir

با تشکر.
لطفا مآخذ مورد استفاده خودتان را هم جهت استفاده بیشتر ذکر بفرمائید.

----------


## mp2009

ممنون بهروز خان از این کار جالبت . در مورد ساخت KeyGen برای سایت هم یه توضیح بدی ممنون میشم

----------


## Behrouz_Rad

> لطفا مآخذ مورد استفاده خودتان را هم جهت استفاده بیشتر ذکر بفرمائید.


ماخذی نداره!
تجارب شخصی هستند... کار + مطالعه + مواجهه با مشکل



> در مورد ساخت KeyGen برای سایت هم یه توضیح بدی ممنون میشم


ارتباطی با موضوع این تاپیک پیدا نمی کنه.

----------


## Behrouz_Rad

*امنیت ViewState*

ViewState مفهومی در برنامه های ASP.NET برای حفظ وضعیت کنترل های صفحه در هنگام PostBack هست.
ViewState می تونه توسط فرد مهاجم دستکاری بشه و داده های ارسال شده رو مثلا مستعد حملات XSS کنه. (در مورد XSS به زودی می نویسم) 
ASP.NET قابلیتی رو با نام Message Authentication Check که به اختصار MAC نامیده میشه فراهم می کنه تا صحت ViewState برای عدم دستکاری شدن اون بررسی بشه. (MAC گاهی اوقات مخفف Machine Authentication Check نیز در نظر گرفته میشه)
EnableViewStateMac به طور پیش فرض فعال هست.
وضعیت کنترل های صفحه به صورت یک مقدار رشته ای که با یک الگوریتم رمزنگاری 64 بیتی کد شده همراه با صفحه به کلاینت ارسال میشه. این مقدار در یک فیلد مخفی با نام VIEWSTATE__ قرار می گیره که در صورتی که Source صفحه رو در مرورگر ببینید، این مقدار مشهود هست.
در صورتی که EnableViewStateMac فعال باشه، بر روی ViewState الگوریتم SHA1 اعمال میشه (کلید این الگوریتم Hash در تگ <machineKey> فایل machine.config تعریف شده و توسط LSA به طور خودکار تولید میشه) و یک مقدار Hash شده به دست میاد که این کد قبل از ارسال ViewState به کلاینت به انتهای اون اضافه میشه.
این کد پس از PostBack صفحه مجددا بررسی میشه و اگر ViewState توسط فرد مهاجم دستکاری بشه، مسلما مقدار متفاوتی از مقدار اولیه به دست میاد. در این هنگام خطایی رخ میده و ViewState رو Invalid اعلام می کنه.

نتیجه گیری پایانی:
آن چه که مسلم هست اینه که هر عمل رمزنگاری و رمزگشایی به خودیه خود مقداری از زمان رو هدر میده اما اون چیزی که بسیار مهم تر هست، امنیت برنامه ی شماست که این زمان ناچیز در کنار استفاده ی صحیح و بجا از ViewState عامل محسوسی به حساب نمیاد.

----------


## hamed_bostan

> 1) الگوریتم Rijndael برای رمزنگاری متقارن خوب هست.


منظور از رمز نگاری متقارن (Symmetric Key Cryptosystem)رمزنگاری ای هست که رمز نگاری و رمز گشایی اطلاعات با کلیدی مشابه صورت میگیره . برای اشنایی بیشتر انواع دیگری هم از جمله رمز نگاری کلید عمومی (Public Key Cryptosystem) هم وجود داره کلید که به جای یک کلید دو کلید مجزا برای رمزنگاری و رمز گشایی داره. برای اطلاعات کاملتر و بیشتر دوستان میتونن  به کتاب امنیت اطلاعات از انتشارات نص از دکتر علی ذاکر الحسینی و مهندس احسان ملکیان مراجعه کنن

----------


## hamed_bostan

امید وارم به درد دوستان بخوره

----------


## Behrouz_Rad

*محافظت از فایل ها از دسترسی غیر مجاز:*

DNN ماژولی برای مدیریت خطاها داره که خطاها رو در یک فایل XML ذخیره می کنه.
در بررسی کدهای DNN مورد جالبی رو دیدم که می تونه ایده ی خوبی برای محافظت از فایل ها از دسترسی غیر مجاز باشه.
وقتی درخواستی به IIS ارسال میشه، اون درخواست تنها در صورتی توسط IIS هندل میشه که جزء پسوندهایی باشه که برای IIS شناخته شده است.
برای دیدن لیست این پسوندها در IIS بر روی Default Web Site راست کلیک و گزینه ی Properties رو انتخاب کنید. در سربرگ Home Directory بر روی دکمه ی Configuration کلیک کنید.
فرض کنید نیاز دارید تا فایل های ZIP رو از دسترسی کاربر غیر مجاز دور نگاه دارید.
دو راه دارید:
1) پوشه ی محتوی فایل های ZIP رو به عنوان پوشه ی Protected از طریق Control Panel معرفی کنید.
2) این کار رو به IIS واگذار کنید.

اگر به روش اول عمل کنید، با محدودیت هایی مواجه میشید. مثلا فرض کنید پرتالی ایجاد کردید و این پرتال رو به مشتری میدید. اگر هاستی که مشتری از اون استفاده می کنه امکان Protected Folders رو فراهم نکنه، با مشکل مواجه میشید. و یا فرضا فایل مورد نظر شما به هر دلیلی باید در ریشه ی اصلی سایت وجود داشته باشه. در این حالت اگر یک Site Map داشته باشید، موتور جستجوگر نمی تونه به Site Map شما دسترسی داشته باشه.

و اما روش دوم:
واگذار کردن وظیفه ی حفاظت از فایل ها به IIS روش خوبی هست اما پسوند فایل باید به IIS معرفی بشه. فایل ZIP جزء پسوندهای شناخته شده توسط IIS نیست و طبیعتا باید این پسوند رو به اون معرفی کرد.
کمتر هاستی این کار رو برای شما انجام میده و اگر هم انجام بده در قبال اون هزینه ای رو دریافت می کنه.
ترفندی که میشه در اینجا استفاده کرد، تغییر پسوند فایل ZIP به یکی از پسوندهایی است که توسط IIS شناخته شده است. DNN پسوند resourcers. رو بدین منظور استفاده کرده تا اگر فردی آدرس مستقیم فایل رو در Address bar وارد کرد، چون پسوند resources. جزء پسوندهایی هست که IIS اون رو هندل می کنه، پس به راحتی میشه دسترسی به این فایل رو کنترل کرد.
اگر خواستید به کاربر اجازه ی دانلود فایل رو بدید، به راحتی با Stream کردن فایل می تونید این کار رو انجام بدید.
همون طور که احتمالا می دونید، یکی از خطوط دانلود فایل به طریق Stream، تعیین هدر "Content-Disposition" هست که در اون می تونید "نام و پسوند واقعی" فایل رو قرار بدید:

Response.AddHeader("Content-Disposition", "attachment; filename=myFile.zip")


روش جالبیه. ازش استفاده کنید.

----------


## DotNet_King

یه مقاله راجع به محدود کردن موتورهای جستجو از نمایش
صفحاتی خاص که ما تایین می کنیم. 

 Robots.rar (372.3 کیلوبایت)

----------


## eyes_shut_number1

سلام! ایا با گذاشتن یک کانتر که بیاد مثلا از 15 بشماره و بعدا که صفر شد بیاد دکمه ثبت را فعال کنه میتونه به امنیت کمک کنه؟ برای جلوگیری از حمله هکر ها که بیاند اطلاعات پشت سر هم رو وارد دیتابیس کنند؟ منظورم اینه که میشه به جای سیکیوریتی ایمیج استفادش کرد> اصلا راه درستی هست؟

----------


## Behrouz_Rad

> سلام! ایا با گذاشتن یک کانتر که بیاد مثلا از 15 بشماره و بعدا که صفر شد بیاد دکمه ثبت را فعال کنه میتونه به امنیت کمک کنه؟ برای جلوگیری از حمله هکر ها که بیاند اطلاعات پشت سر هم رو وارد دیتابیس کنند؟ منظورم اینه که میشه به جای سیکیوریتی ایمیج استفادش کرد> اصلا راه درستی هست؟


دوست من!
فرد مهاجم اینقدر بیکار نیست که حتی بخواد وارد سایت شما باشه که از طریق اون داده ای رو به سرور ارسال کنه.
یک بار بازدید سایت شما و استفاده از یک Http Sniffer کافی هست تا از ساختار Packet ارسالی مطلع شد.

موفق باشید.

----------


## Behrouz_Rad

*محافظت از برنامه در برابر حملات XSS*

حملات XSS یکی از خطرناکترین حملاتی هستند که بسیاری از سایت ها، پرتال ها و فروم های معروف نیز مستعد این نوع حملات هستند.
مستعد بودن برنامه به تزریق کدهای Client Side از طریق ورودی برنامه و عدم تعیین اعتبار ورودی باعث ایجاد حملات XSS میشه.
البته XSS گاهی اوقات با نام CSS نیز شناخته میشه اما به این دلیل که با Cascade Style Sheet اشتباه گرفته نشه، با عنوان XSS شناخته و استفاده میشه.
بیشترین و متداولترین خسارتی که XSS به برنامه وارد می کنه، دزدیدن Cookie کاربر و استفاده از اون به نفع فرد مهاجم هست.
حالتی رو در نظر بگیرید که کاربر فرمی رو پر می کنه و اون رو ارسال می کنه. اگر در فیلدهای این فرم به جای اطلاعات مرسوم، کدهای Client Side وارد شده باشند، کاربر به راحتی در معرض آسیب پذیری خطرناکی قرار می گیره.
فرض کنید من به عنوان فرد مهاجم، عبارت <script>alert(document.cookie);</script> رو وارد کنم.
این عبارت به عنوان یک مقدار ذخیره میشه. همچنین یک کوکی تصدیق هویت یا یک کوکی که حاوی اطلاعات مهمی (مثلا شماره حساب بانکی) از کاربر هست بر روی سیستم کاربر ذخیره کردیم.
در ادامه فرض کنید که قسمتی رو برای نمایش اطلاعات وارد شده به کاربر در نظر گرفتید. کاربر در زمان لود صفحه، شماره حساب خودش رو می بینه!
من می تونم ورودی رو کمی تغییر بدم تا این اطلاعات برای من ارسال بشه. چون در اینجا قصد بر آموزش هک نیست وارد جزئیات نمیشم.

توجه داشته باشید که مقصود از ورودی هر جایی در برنامه ی شماست که اطلاعات از اون طریق به سرور ارسال میشه. این مکان می تونه Query String و هدرهای HTTP نیز باشه.

راه های مختلفی برای مقابله با حملات XSS وجود داره.

اولین و مهم ترین گام، تعیین اعتبار مقادیر ورودی هست.
بهترین راه برای تعیین اعتبار، استفاده از Reqular Expressions یا همان عبارات باقاعده هست.
دومین گام، کد کردن مقادیر ورودی هست.
برای کد کردن مقادیر ورودی میشه از متد HtmlEncode کلاس HttpUtility استفاده کرد.
برای کد کردن URL از متد UrlEncode کلاس HttpUtility استفاده کنید.

نکته ی بسیار مهمی که باید به اون توجه داشته باشید این هست که فقط به کد کردن داده ها در ورودی اکتفا نکنید. اگر به هر دلیلی داده های کد نشده در دیتابیس ذخیره بشن (مثلا در حالتی که یک دیتابیس توسط دو برنامه استفاده میشه و یکی از برنامه ها مستعد XSS هست) برنامه ی دیگه نیز می تونه آسیب پذیر باشه. در این حالت حتی هنگام Bind کردن منبع داده به کنترل و مثلا استفاده از توابع Eval یا Bind، قبل از آن متد HtmlEncode رو به شکل ذیل فراخوانی کنید:

<%# HttpUtility.HtmlEncode(Eval("myFieldName")) %>


نکته 1:
در IE 6.0 SP1 خصوصیتی با نام HttpOnly برای کوکی ها در نظر گرفته شد که در صورتی که یک کوکی این خصوصیت رو داشته باشه، اجازه ی دسترسی به اون به کدهای Client Side داده نمیشه.
این خاصیت رو می تونید از طریق تنظیم خاصیت HttpOnly کلاس HttpCookie تنظیم کنید.
خوشبختانه پشتیبانی از این خصوصیت از نسخه ی 2.0.0.5 در Firefox نیز لحاظ شده اما باگی در Firefox وجود داره که با استفاده از هسته ی اصلی AJAX که همون XMLHTTPRequest هست میشه به کوکی دسترسی داشت.
این باگ در IE 7.0 برطرف شده.
جزئیات بیشتر در مورد این باگ رو در لینک ذیل بخونید:
http://ha.ckers.org/blog/20070719/fi...mlhttprequest/

نکته 2: ابزارهایی همچون Anti-Cross Site Scripting Library توسط مایکروسافت به منظور مقابله با XSS در ASP.NET برای برنامه نویسان عرضه شده.

نتیجه گیری پایانی: وجود خصوصیت HttpOnly که البته خوب هست دلیلی بر این نیست که نسبت به حملات XSS بی توجه باشید.

----------


## Behrouz_Rad

*محافظت از برنامه در برابر Session Hijacking*

یکی از قدیمی ترین حملاتی که به برنامه های وب صورت می گیره، Session Hijacking (سرقت Session) هست.
برای آشنایی با این نوع حمله بهتره که کمی در مورد نحوه ی هندل کردن Session ها در ASP.NET صحبت کنیم.
Session برای نگهداری داده هایی به کار میره که برای هر کاربر منحصر به فرد هستند. مثلا نمایش نام کاربر پس از لوگین، در تمامی صفحات سایت.
Session در حافظه ی سرور نگهداری میشه. ASP.NET برای اینکه بتونه تشخیص بده که هر Session متعلق به کدام کاربر هست، مشخصه ای یکتا برای هر Session ایجاد می کنه و این مشخصه رو در یک کوکی با نام ASP.NET_SessionID قرار میده. با ایجاد هر درخواست به سرور، ASP.NET مشخصه ی موجود در این کوکی رو بررسی می کنه و از این طریق متوجه میشه که کدام Session در حافظه ی سرور متعلق به کاربر هست.
به این مشخصه ی یکتا Session ID گفته میشه.
پر واضح هست که اگر کوکی ها در مرورگر کاربر غیر فعال باشند، استفاده از Session عملا کاربردی نداره.

به طور خلاصه اگر فردی بتونه این کوکی رو به سرقت ببره، به راحتی می تونه خودش رو صاحب Session شما معرفی کنه.
میزان خطری که Session Hijacking در پی داره به نوع اطلاعاتی که در اون هست و نحوه ی استفاده ی برنامه نویس از Session بستگی داره.
به عنوان مثال، در حالتی که از Session تنها برای نگهداری نام کاربری استفاده میشه، سرقت Session سودی برای فرد مهاجم نداره چون تنها چیزی که ممکنه نصیب اون بشه (که البته باز هم بستگی به نحوه ی برخورد برنامه نویس با Session داره) نام کاربری هست!
اما اگر مثلا شماره ی حساب بانکی یا سطح دسترسی کاربر در Session ذخیره میشه با خطری جدی مواجه هستید.

Session Hijacking معمولا به دو طریق انجام می گیره:
1) حدس زدن Session ID
2) سرقت کوکی حاوی Session ID

*حدس زدن Session ID*
این مورد به ندرت اتفاق می افته چون ASP.NET به طور خودکار این ID رو تولید می کنه و اعدادی که تولید میشن 120 بیتی و کاملا راندوم هستند. البته میشه تولید این ID ها رو خودتون با استفاده از کلاس SessionIDManager بر عهده بگیرید اما این کار اصلا پیشنهاد نمیشه. فرضا اگر روال شما برای اختصاص SessionID یک عدد تصاعدی مثل فیلدهای از نوع AutoNumber در SQL Sever باشه، فرد مهاجم می تونه با بررسی چند باره ی محتویات کوکی ذکر شده، از این روش مطلع بشه.

*سرقت کوکی حاوی Session ID*
در مورد سرقت کوکی در مقاله ی قبلی توضیح دادم. XSS می تونه یکی از روش هایی باشه که منجر به سرقت کوکی ها میشه.

*راهکار مقابله به Session Hijacking*
راهکاری که میشه استفاده کرد، "منحصر به فرد تَر کردن" Session ID هست.
بدین شکل که برخی مشخصه های کاربر همانند IP و User Agent رو همراه با یک کلید رمز و خود SessionID به یک الگوریتم Hash همانند HMACSHA1 که یک کلید رو برای رمزنگاری می پذیره داد و رشته ی رمزنگاری شده رو به انتهای SessionID اضافه کرد.
فرایند فوق رو به راحتی میشه از طریق یک HttpModule پیاده سازی کرد.
روال EndRequest مکان خوبی برای الصاق مشخصه ی به دست آمده به انتهای SessionID هست.
روال BeginRequest نیز می تونه برای بررسی صحت این مشخصه استفاده بشه.

کدنویسی بر عهده ی خودتون ;)

نتیجه گیری پایانی: هر چند که هیچ روشی همواره امنیت رو به طور صد در صد تضمین نمی کنه، اما امنیت رو باید یک وضعیت نسبی در نظر گرفت. مجموعه تلاش هایی که انجام میدیم تا راه نفوذ به برنامه رو برای فرد مهاجم سخت تر کنیم.

----------


## hamed_bostan

> *راهکار مقابله به Session Hijacking*
> راهکاری که میشه استفاده کرد، "منحصر به فرد تَر کردن" Session ID هست.
> بدین شکل که برخی مشخصه های کاربر همانند IP و User Agent رو همراه با یک کلید رمز به یک الگوریتم Hash همانند HMACSHA1 که یک کلید رو برای رمزنگاری می پذیره داد و رشته ی رمزنگاری شده رو به انتهای SessionID اضافه کرد.
> فرایند فوق رو به راحتی میشه از طریق یک HttpModule پیاده سازی کرد.
> روال EndRequest مکان خوبی برای الصاق مشخصه ی به دست آمده به انتهای SessionID هست.
> روال BeginRequest نیز می تونه برای بررسی صحت این مشخصه استفاده بشه.



خوب بهروز جان اگر ما sessionID  رو کلید بگیریم و یا به هر شکل این SessionID  بعد از ورود کاربر به سیستم نقش کلیدی بازی کنه اگر Hijacker  این کوکی رو روی سیستمش ایجاد کنه خودش و به سایت ما بیاد با همون نقش کاربر شناسایی شده ما شناخته میشه و اینجا به هر حال سیستم متوجه نمیشه که این اون نیست (البته در صورتی که فقط به این SessionID  اکتفا بشه) مگر اینکه از ClientIP  شخص هم جز پارامتر ها استفاده کنیم که این هم خیلی معتبر نیست . ایا روشی پیشنهاد  می کنی شما که در این روش حتی اگه ه.ک.ر کوکی رو هم ایجاد کرد سیستم تشخیصش بده؟ یا در کل راه حلی جامع واسه این عمل ؟

بابت اینکه IP و ... رو هم به تهsessionID  اضافه کنیم گفتی شما اما اگر کوکی رو شخص ایجاد کنه  رو سیستمش این ها چه فرقی میکنه؟ (شاید من درست متوجه نشدم اگه ممکنه این قسمت رو باز ترش کن تا دو هزاری کج من بیفته)

----------


## Behrouz_Rad

> خوب بهروز جان اگر ما sessionID  رو کلید بگیریم و یا به هر شکل این SessionID  بعد از ورود کاربر به سیستم نقش کلیدی بازی کنه اگر Hijacker  این کوکی رو روی سیستمش ایجاد کنه خودش و به سایت ما بیاد با همون نقش کاربر شناسایی شده ما شناخته میشه و اینجا به هر حال سیستم متوجه نمیشه که این اون نیست (البته در صورتی که فقط به این SessionID  اکتفا بشه) مگر اینکه از ClientIP  شخص هم جز پارامتر ها استفاده کنیم که این هم خیلی معتبر نیست . ایا روشی پیشنهاد  می کنی شما که در این روش حتی اگه ه.ک.ر کوکی رو هم ایجاد کرد سیستم تشخیصش بده؟ یا در کل راه حلی جامع واسه این عمل ؟
> 
> بابت اینکه IP و ... رو هم به تهsessionID  اضافه کنیم گفتی شما اما اگر کوکی رو شخص ایجاد کنه  رو سیستمش این ها چه فرقی میکنه؟ (شاید من درست متوجه نشدم اگه ممکنه این قسمت رو باز ترش کن تا دو هزاری کج من بیفته)


من 4 تا پارامتر رو قصد داشتم پیشنهاد بدم که مثل اینکه فراموش کردم Session ID رو هم ذکر کنم.
1) IP
User Agent (2
3) یک کلید عمومی
4) Session ID

اگر بدبینانه بخوایم نگاه کنیم، IP دو نفر می تونه شبیه به هم باشه.
احتمال شباهت User Agent دو کاربر هم که خیلی خیلی زیاد هست.
کلید عمومی بهترین راهکار هست. چون فرد مهاجم به هیچ وجه از اون اطلاعی نداره.
برای اینکه عبارت Hash تولید شده کاملا راندوم باشه، نیاز به مشخصه ای هست که راندوم باشه. Session ID کاملا راندوم هست و قسمت اصلی کار ما محسوب میشه.
بنابراین، اگر مهاجم بتونه IP، User Agent و Session ID رو جعل کنه، نمی تونه کلید عمومی رو حدس بزنه و این نقطه ی قوت کار ماست.
البته تمامی این تفاسیر در صورتی هست که مهاجم بتونه تشخیص بده که ما از چه الگوریتم و روشی برای تصدیق صحت Session استفاده می کنیم که احتمالا باید به علوم غیبه مجهز باشه! ;)

موفق باشید.

----------


## illegalyasync

دخیل کردن ip کاربر هیچ وقت کار درستی نیست خیلی از کاربرها یا پشت nat هستن یا پشت ip pool و هر دو مسئله باعث میشه چنین سیستمی جواب نده .
رمزنگاری و هش و بقیه چیزها فقط بازی کردن با کد هستش ! این هیچ کمکی به امنیت شما نمیکنه به دو دلیل
هکر یا به جلسه نفوذ کرده ( xss ) یا جلسه رو شنود کرده ( کوکی )
در حالت اول دیگه همه از xss shell استفاده میکنن که دستورات رو مستقیم tunnel میکنه به جلسه کاربر ! یعنی هیچ اهمیتی نداره که چه مکانیزمی برای تفکیک کاربر جعلی و واقعی استفاده شده باشه چون دستورات که میتونن تو یه فایل xml‌روی سرور هکر ذخیره شده باشن مستقیم پمپ میشن به جلسه کاربر . چند تا فریم ورک برای تونل الان وجود داره 
در حالت دوم که جلسه شنود شده باشه ساختن user agent جعلی که خیلی ساده هستش بقیه مطالب بین کاربر جعلی و واقعی مشترکه و هیچ راه دفاعی وجود نداره . رمزنگاری هیچ کمک نمیکنه . خیال نکنین در هر مسئله ای اگر چیزی رو رمز کنیم و کلمه هش رو بکار ببریم به نوعی امنیت افزایش پیدا میکنه . وقتی چیزی رو رمز میکنیم که یا هکر در همون جلسه مشارکت داره ( تونل ) یا کل محتویات جلسه حتی کلید رمزنگاری رو داره ( شنود ) دیگه هیچ محافظتی وجود نداره . بعدا اگر وقت کردم دو سه تا روش برای حل این مسائل مینویسم

----------


## Behrouz_Rad

> وقتی چیزی رو رمز میکنیم که یا هکر در همون جلسه مشارکت داره ( تونل ) یا کل محتویات جلسه حتی کلید رمزنگاری رو داره ( شنود ) دیگه هیچ محافظتی وجود نداره .


مرسی محمد از توجهت.
ممنون میشم در مورد روش هایی که گفتی توضیح بدی.

مرسی.

----------


## hamed_bostan

> وقتی چیزی رو رمز میکنیم که یا هکر در همون جلسه مشارکت داره ( تونل ) یا کل محتویات جلسه حتی کلید رمزنگاری رو داره ( شنود ) دیگه هیچ محافظتی وجود نداره . بعدا اگر وقت کردم دو سه تا روش برای حل این مسائل مینویسم


بی صبرانه منتظر راه حل شما هستیم . فکر میکنم اکثر بچه های کد نویس فقط با رمز کردن و یا بی اطلاعی مثل من فقط خودشون رو گول میزنن که برنامه هاشون امن هست . اگر تو این تاپیک به یهچند تا راه حل درست و مطمعن برسیم خیلی عالیه . مخصوصا اینکه میتونیم از اقا بهروز و شما و دیگر دوستانی که تو اطن مسائل تجربه دارن استفاده کنیم و به یه نتیجه واحد برسیم

----------


## Behrouz_Rad

> دخیل کردن ip کاربر هیچ وقت کار درستی نیست خیلی از کاربرها یا پشت nat هستن یا پشت ip pool و هر دو مسئله باعث میشه چنین سیستمی جواب نده .
> رمزنگاری و هش و بقیه چیزها فقط بازی کردن با کد هستش ! این هیچ کمکی به امنیت شما نمیکنه به دو دلیل
> هکر یا به جلسه نفوذ کرده ( xss ) یا جلسه رو شنود کرده ( کوکی )
> در حالت اول دیگه همه از xss shell استفاده میکنن که دستورات رو مستقیم tunnel میکنه به جلسه کاربر ! یعنی هیچ اهمیتی نداره که چه مکانیزمی برای تفکیک کاربر جعلی و واقعی استفاده شده باشه چون دستورات که میتونن تو یه فایل xml‌روی سرور هکر ذخیره شده باشن مستقیم پمپ میشن به جلسه کاربر . چند تا فریم ورک برای تونل الان وجود داره 
> در حالت دوم که جلسه شنود شده باشه ساختن user agent جعلی که خیلی ساده هستش بقیه مطالب بین کاربر جعلی و واقعی مشترکه و هیچ راه دفاعی وجود نداره . رمزنگاری هیچ کمک نمیکنه . خیال نکنین در هر مسئله ای اگر چیزی رو رمز کنیم و کلمه هش رو بکار ببریم به نوعی امنیت افزایش پیدا میکنه . وقتی چیزی رو رمز میکنیم که یا هکر در همون جلسه مشارکت داره ( تونل ) یا کل محتویات جلسه حتی کلید رمزنگاری رو داره ( شنود ) دیگه هیچ محافظتی وجود نداره . بعدا اگر وقت کردم دو سه تا روش برای حل این مسائل مینویسم


راهکاری که به نظر من میرسه، نگهداری یک مقدار کد شده در View State هست.
با توجه به اینکه View State تنها در صفحه ی وب قرار می گیره، میشه در هنگام ایجاد Request وجود اون رو بررسی کرد.
SID همراه با مقدار کد شده ی ViewState در جایی مثل Cache ذخیره بشن و در هنگام ایجاد درخواست، SID ارسال شده با مقدار منتسب به اون در ViewState مقایسه بشه.
ارسال پاسخ نیز مجددا با ارسال همین مقدار ViewState یا حتی تغییر اون و ارسال یک مقدار جدید به صفحه می تونه همراه باشه.
بدین طریق مهاجم حتی با داشتن کوکی و جعل IP و User-Agent (که البته دیگه نیازی بهشون نیست) هم نمی تونه سودی ببره.

به نظرم راه خیلی مطمئنی هست.

----------


## m.hamidreza

> *محافظت از برنامه در برابر Session Hijacking*
> 
> به عنوان مثال، در حالتی که از Session تنها برای نگهداری نام کاربری استفاده میشه، سرقت Session سودی برای فرد مهاجم نداره چون تنها چیزی که ممکنه نصیب اون بشه (که البته باز هم بستگی به نحوه ی برخورد برنامه نویس با Session داره) نام کاربری هست!


من این کار رو کردم ... منظور از "بستگی به نحوه ی برخورد برنامه نویس با Session داره" چیه ؟
مهندس بهروز این پست برادر محمد رو میشه یه ذره ساده تر بازش کنی ؟  :خجالت:

----------


## Behrouz_Rad

مثلا ممکنه برنامه نویس "نام کاربری" رو به عنوان مجوز دسترسی به مکانی در نظر بگیره اما "نام کاربری" برای برنامه نویس دیگه ای فقط به عنوان نمایش نام کاربری در صفحات استفاده بشه.

برادر محمد واضح گفت. با کجاش مشکل داری؟

----------


## hamed_bostan

بهروز جان بد نیست بعد یا قبل از اینکه برادر محمد راهکارش رو بده واسه راکد نموندن تاپیک در مورد encrypt Ch یا  encode کردن URL  ازسالی بین صفحات یه توضیحی بدین . من خودم که تو این مورد مشکل دارم و هنوز راه اصولی ای برای ارسال پارامتر به صورت امن بین صفحات پیدا نکردم :قلب:

----------


## Behrouz_Rad

باید یک Handler بنویسی تا برخی کاراکترهای خاص در URL رو حذف کنه.
مثلا .. یا /.. حذف بشن. البته اگر سرور امن باشه (مثلا URL Scan رو نصب کرده باشه) این کار ضرورتی نداره.
همچنین باید همیشه URL رو Encode کنی تا مثلا <script> نتونه در Query String وارد بشه.

موفق باشید.

----------


## m.hamidreza

> برادر محمد واضح گفت. با کجاش مشکل داری؟


xss shell و tunnel چیه ؟




> رمزنگاری و هش و بقیه چیزها فقط بازی کردن با کد هستش ! این *هیچ کمکی* به امنیت شما نمیکنه به دو دلیل
> هکر یا به جلسه نفوذ کرده ( tunnel ) یا جلسه رو شنود کرده ( کوکی )


الان منظور  اینه که ه.ک.ر بعد از نفوذ چون دارنده ی اون جلسه هست هر کاری که در حد دسترسی اون جلسه باشه میتونه انجام بده ! حالا چه Hash باشه چه نباشه . مهم اینه که جلسه در اختیار فرد مهاجمه و فرد مهاجم الان معرف کاربر واقعیه،حالا شاید تو خود session اطلاعات محرمانه ای هم باشه اینجا اگه Hash شده باشه که به امنیت کمک میکنه .



> وقتی چیزی رو رمز میکنیم که یا هکر در همون جلسه مشارکت داره ( تونل ) یا کل محتویات جلسه حتی کلید رمزنگاری رو داره ( شنود )


اینا مگه معادل هم نیستن :
هکر در همون جلسه مشارکت داره ( تونل ) =  هکر یا به جلسه نفوذ کرده ( tunnel )
کل محتویات جلسه حتی کلید رمزنگاری رو داره ( شنود ) = یا جلسه رو شنود کرده ( کوکی )
این میشه همون بالایی دیگه ! پس کی باید Hash کرد ؟

----------


## Behrouz_Rad

> xss shell و tunnel چیه ؟


XSS Shell ابزاری هست که ایجاد حملات XSS رو بسیار راحت می کنه.
XSS Tunnel یک جور پروکسی هست که دستورات از طریق اون به سیستم قربانی ارسال میشن و پاسخ دریافت میشه.




> حالا شاید تو خود session اطلاعات محرمانه ای هم باشه اینجا اگه Hash شده باشه که به امنیت کمک میکنه .


مهاجم نمی تونه به محتویات Session دسترسی داشته باشه. اون فقط در زمینه ی Session هست. همین! اینجا اصلا بحث بر سر رمزنگاری یا کد کردن اطلاعات Session نیست.

متاسفانه مباحث امنیتی مثل تیغ دو لبه می مونن.
اگر زیاد وارد جزئیات بشی خیلی ها از اون سوء استفاده می کنند.
پس لطفا سعی کنید زیاد وارد جزئیاتی نشید که نشه در مورد اونها به صورت عمومی صحبت کرد ;)

----------


## m.hamidreza

> مهاجم نمی تونه به محتویات Session دسترسی داشته باشه. اون فقط در زمینه ی Session هست. همین! اینجا اصلا بحث بر سر رمزنگاری یا کد کردن اطلاعات Session نیست.


من با این قاطی کردم :



> به عنوان مثال، در حالتی که از Session تنها برای نگهداری نام کاربری استفاده میشه، سرقت Session سودی برای فرد مهاجم نداره چون تنها چیزی که ممکنه نصیب اون بشه (که البته باز هم بستگی به نحوه ی برخورد برنامه نویس با Session داره) نام کاربری هست!
> اما اگر مثلا شماره ی حساب بانکی یا سطح دسترسی کاربر در Session ذخیره میشه با خطری جدی مواجه هستید.


پس فقط مالکیت سشن Hijack میشه نه محتویات Session ؟

----------


## mehrdad201

من راستش در این زمینه دارم تحقیق میکنم (البته من تازه کارم و زیاد قوی نیستم اما دارم در این مورد اطلاعات جمع می کنم.)


دوستان لطفا هر مقاله ای که در این زمینه پیدا می کنن لینکش رو بذارن تا همه بتونن استفاده کنن.

----------


## Behrouz_Rad

> پس فقط مالکیت سشن Hijack میشه نه محتویات Session ؟


بله.



> دوستان لطفا هر مقاله ای که در این زمینه پیدا می کنن لینکش رو بذارن تا همه بتونن استفاده کنن.


اینجا فقط مقاله ی فارسی قرار بدید.

----------

