امنیت خود را تامین کنید

elahi

مدیریت
مدیر کل انجمن
با سلام .
چون اغلب در کتاب های آموزشی asp حرفی از امنیت برنامه ها زده نشده بنده قصد دارم اگر شد آموزش هایی درباره امنیت برنامه های تحت وب با asp رو براتون بذارم . مساله ای که باعث میشه خیلی ها گنگ باشن در این زمینه .
اگر مطلب خارجی هم بود میذارم که انشالله یک منبع خوب هم جمع آوری بشه .
اما قبلش مجبورم شما رو کمی راغب کنم به این که این تاپیک رو از یاد نبرید --> پس تحویل بگیرید :
آیا شما هم از هک شدن مداوم سایت خود که بر حسب تصادف با ASP نوشته شده است عصبی شدید ؟
آیا چپ و راست سایت شما مورد هجوم قرار می گیرد ؟
چند بار عبارت کذایی ... Hacked By را در وب سایت خود مشاهده کرده اید ؟
چند بار اقدام به امن کردن برنامه های تحت وب خود که باز هم تصادفا با ASP نوشته شده اند کرده اید ؟
 

elahi

مدیریت
مدیر کل انجمن
قدم اول :

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

خلاصه : حتی المکان صفحه ورود مدیر عمومی نباشه . دایرکتوری(پوشه اش) معلوم نباشه . یه خورده هم دور از ذهن باشه . البته همه این ها از محکم کاریه . اما اگه خیلی به صفحه ورودتون مطمئن هستید میتونید اون رو به صورت عمومی در وب سایتتون قرار بدید و کمی با هکر شوخی کنید .

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

elahi

مدیریت
مدیر کل انجمن
قدم دوم :

در ادامه مطلب قبلی باید این نکته رو بگم که حالا وقت این رسیده یک صفحه ورود خوب و امن داشته باشین . اصولا قاعده ای که در اکثر سیستم های ورود رعایت میشه اینه که یوزرنیم + پسورد از مراجعه کننده خواسته میشه . بعد میره توی دیتابیس و صحت پسورد تایید میشه . session تشکیل میشه . به صفحه اصلی مدیریت ارجاع داده میشه .
حالا ممکنه یوزرنیم و پسورد همیشه با یک عبارت ثابت سنجیده بشه . یعنی کار به دیتابیس کشیده نشه .
if request("username") = "admin" and request("password")="myadmin" then
session("admin")=true
response.redirect "admin.asp"
else
session("admin")=false
response.redirect "login.asp?msg=error"
end if
اما قضیه بغرنج قضیه همون وارد شدن ورودی کاربر به دیتابیس بدون هیچ گونه عملی رو داده هست . که اگه این قسمت رو رعایت کنید تا حد زیادی امنیت برنامه تون رو تامین کردید .
اینجا درباره تاریخچه و اصول sql injection یا همون تزریق اطلاعات نمی خوام وارد بشم . مقالات بسیار زیاد و توضیحات فراوانی در این زمینه هست . ما فقط میخوام راه مقابله باهاش رو یاد بدیم دیگه بقیه توضیحات "در این مقال نمی گنجد" . اما از اونجایی که ندانسته کار کردن خطاست چندتا منبع میذارم که مطالعه کنید .
http://kapda.ir/pedia/SQL_Injection
http://en.wikipedia.org/wiki/Sql_injection

خب برگردیم به کار خودمون . تامین امنیت برنامه های وب که با asp نوشته شدن .
اما اگه قرار هست که یوزرنیم و پسوردی که وارد می کنیم همین طوری یه دفعه بره تو دیتابیس و جواب بیرون بیاد در یک کلام میشه گفت یک حرکت "هکر شاد کن" .
مهم نیست که دستورات sql ما چطور کار می کنند و به چه روشی به تعیین هویت می پردازن مهم اینه که در همه اونها هر عبارتی که داخل query قرار میگیره یه فیلترینگ کوچیکی بشه .
حداقل برای دوستانی که با access کار می کنن بگم که فیلتر کردن کوتیشن تکی لازم هست .
برای کسانی هم که با sql کار میکنن -- و ; و " لازم هست . البته کاراکترهای دیگه هم هستن مثل تمامی اون چیزهایی که روی دکمه های اعداد درج شدن . مثل !@#$%^&*)(=
پس یک نمونه ضعیف از Query

"SELECT * FROM users WHERE name = '" & userName & "'" & " and pass = '" & password & "'"

و نمونه قابل قبول برای اکسس :

"SELECT * FROM users WHERE name = '" & replace(userName,"'","''") & "'" & " and pass = '" & replace(password,"'","''") & "'"

توضیح : replace برای امن کردن و تبدیل تک کوتیشن به دو کوتیشن به کار رفت .

اما این نکته رو هم یادتون نره که در این الگوریتم session فراموش نشه . چون فرض کنید بدون session بخواین صفحه رو منتقل کنید به admin.asp . خب حالا فرض کنید هکر شانسی مستقیم url رو http://site.com/admin/admin.asp زد . بعد هم میره صفحه ادمین . فردا میاین میبینین سایتتون توسط یه گروه هک شده . پس این وسط نقش login.asp چیه ؟ بعد از صحت رمز ورودی ایجاد یک session که در بقیه صفحات مثل admin.asp بدین ترتیب استفاده بشه :

if session("admin") <> true then
response.redirect "login.asp?msg=sorry you must login"
response.end
end if

خلاصه : یک صفحه ورود نسبتا خوب که معمولا الگوریتم مشخصی هم داره اینه که -->
1)گرفتن یوزرنیم و پسورد از بازدید کننده و فیلتر کردن ' و ; و " و -- و دیگر کاراکترها به وسیله تابع replace
2)تعیین اینکه آیا یوزر نیم و پسورد گرفته شده از بازدید کننده (که صد البته منظورم یوزرنیم و پسورد بعد از اجرای فیلتر و محدود کردن اون) صحیح هست یا نه به وسیله sql و asp .
3)اگه صحیح بود تشکیل session و ارجاع به صفحه اصلی مدیریت و چک شدن session در اون صفحه اصلی و سایر صفحات مدیر برای اینکه یه موقع خدای نکرده هکر مستقیم url رو وارد نکرده باشه .
 

elahi

مدیریت
مدیر کل انجمن
به امید خدا خوب داره پیش میره و مطالب کپی / پیست شده و ... نیست . فکر کنم سبک مقالات جدی بعضی جاها واسه کلاس بخشیدن به کار خوبه ولی بعضی وقتها برای درک بهتر مطلب این طور نوشتن بهتره .

قدم سوم :

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

if instr(request("username"),"'") <> 0 and instr(request("password"),"'") <> 0 then
response.write "Thank You admin . Your Username And Password were true"
response.end
end if

خب این کد تعیین میکنه که در username و password آیا کوتیشن به کار رفته یا نه ؟ خب اگه خدای نکرده به کار رفته باشه به هکر پیغام میده که ممنون . شما وارد شدید . رمزتون درست بود . هکر کلی ذوق زده . ولی میبینه هیچ اتفاقی نیفتاد . ولی خوشحاله که سیستم شما رو bypass کرده . خلاصه چند دقیقه کلنجار میره به خیال اینکه کار تمومه ولی دستش به هیچ جا بند نیست . فکر می کنه شاید کوکی درست رو کامپیوترش سیو نشده یا دنبال صفحه اصلی مدیریت میگرده . نه خیر ... شما حسابی اعصاب اون رو بهم ریختید .

خلاصه : از کدها و الگوریتم های تکرار یا منطقی برای خسته کردن و فریب دادن هکر استفاده کنید .
 

elahi

مدیریت
مدیر کل انجمن
قدم چهارم :

اگه گفتید دومین جایی که برای یک هکر چشمک میزنه در asp چی هست ؟ عوض کردن مقدار url ها چون خیلی تو چشم میزنه . حتی گاهی از دانلود کردن mdb هم بیشتر .

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

این url رو در نظر بگیرید .
http://site.com/news.asp?id=10
خب در نگاه اول اگه هکر خوش شانس باشه id به راحتی میره در یک Query بدون هیچ محدودیتی و باز هکر خوش شانس تر اونیه که دیتابیس mssql باشه . دیگه لازم هم نیست روش های کسل کننده access رو اجرا کنه . در mssql دستش باز هست . حالا ایناش مهم نیست . برنامه امن باشه حالا mssql یا access بر میگرده به قابلیت ، سرعت ، سلیقه و ...
کدی که اون پشت اجرا میشه میتونه یه همچین چیزی باشه :
" select * from news where id = " & request("id")


اما این ضعیف ترین نوع کار هست . همون طور که گفتم منجر به sql injection یا تزریق اطلاعات میشه .
دوستانی که خیلی حواسشون به صفحات ورود هست معمولا این قسمت رو یادشون میره . اگر هم یادشون باشه به فرم صفحه ورود عمل می کنن . به خیال خودشون که دیگه امنیت news.asp در حد اعلای خودش هست . مثلا نمونه کد این دوستان این هست :

" select * from news where id = " & replace(request("id"),"'","''")


اما بهتره عرض کنیم این Query فقط کار هکر رو سخت تر می کنه و محدودیت براش به وجود میاره اما اصلا میتونه هیچ کاری هم با این نداشته باشه . چطوری ؟؟؟!؟!؟!
اینطوریه که اصلا کدی که میخواد وارد کنه توش ' نداشته باشه . یعنی کدهای خودش رو در ادامه id وارد کنه بدون ' . فاجــــــــــــــــــعه ...
http://site.com/news.asp?id=10 or 1=1
اینجا قصد ندارم طریقه extract کردن دیتا از دیتابیس رو بگم . ولی دیدید که حتی بدون کوتیشن کارها پیش میره . پس چاره اینه که چک کنید ببینید آیا این داده ورودی عدد هست یا نه . اما یه راه راحت تر . استفاده از cint . روشی که اتوماتیک وار جلوی ورود کوتیشن رو هم میگیره.

" select * from news where id = " & cint(request("id"))


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

خلاصه : در url و جایی که مقدار متغیر ورودی به Query قرار است عدد باشد از cint یا isnumeric استفاده کنید .

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

elahi

مدیریت
مدیر کل انجمن
قدم پنجم :

با xss آشنایی دارید ؟ همون css یا cross_site_scripting . همش یکیه . کدهای مخربی که سمت کاربر(نه سرور) اجرا میشه . اگه با حفره یه مرورگر تلفیق بشه میتونه کاری کنه کل کاربرهای یک سایت رو سیستمشون تروجان نصب بشه ، کوکی بدزده و کارهایی از این قبیل . اول یه سری بزنید :
http://www.kapda.ir/pedia/XSS
در کل چند نوع xss داریم که درجات مختلفی دارن . منظورم از لحاظ درجه خطر بود . اونایی که خیلی متداول هستن نوع 1 و 2 هستن .
دیگه ما اینجا به انواعش کار نداریم . فقط اصطلاحاتش رو بگم که گوشتون آشنا باشه بهشون .
1) نوع اول که معمولا xss یا css میگن .
2) نوع دوم که باعث میشه کدهای html ، javascript و ... در جایی ذخیره بشن و بعد از هربار لود شدن صفحه اجرا بشن . xss میگن بهشون . سایت معروف securityfocus اسمش رو HTML_Injection گذاشته و باقی سایتها Script_Insertion میگن . همشون یکیه .
حالا بریم به سراغ مباحث امنیتیش تو asp .
این آسیب پذیری وقتی به وجود میاد که ما محتوای یه متغیر رو یه دفعه رو صفحه نمایش بیاریم و دست بر قضا این متغیر از کاربر هم گرفته شده باشه . حالا میتونه این متغیر یک متغیر از طریق POST باشه یا GET .
میتونم بگم راحت ترین مثال و متداول ترین حالت صفحه های کامنت هست . دیگه از این راحت تر . این میشه نوع دوم چون فرض کنید شما به جای اینکه اسم خودتون رو وارد کنید میزنید <noscript> . بعد هم کلا اون صفحه کامنت تا پایین از کار میفته . یا مثلا guestbook یا همون دفترچه مهمان . از نوع اول هم مثال بزنم اینطوری :
login.asp?error_msg=please login
بعد هم اگه برنامه آسیب پذیر باشه error_msg رو یکی توش کد html یا javascript میذاره ولی این حالت درجه خطرش خیلی کمتره چون فقط با لینک دادن میشه از این باگ استفاده کرد .
راه حال مناسب در asp
برای کامنت و صفحاتی از این قبیل :

"Select * from comments where id = 'id'"
rs.addnew
rs("name") = request("name")
rs("comment") = request("comment")
rs.update

یا کد مشابه یک خطیش که از insert into table استفاده میشه باید به این حالت تغییر پیدا کنه :

"Select * from comments where id = 'id'"
rs.addnew
rs("name") = server.htmlencode(request("name"))
rs("comment") = server.htmlencode(request("comment"))
rs.update

توضیح : server.htmlencode کدهای <>& رو تبدیل به حالت نمایش میکنه یعنی دیگه کدهای html ، javascript و ... هکر در صفحه نمایش رندر نخواهند شد .

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

response.write request("msg")

که کد مناسبش میشه این :

response.write server.htmlencode(request("msg"))

خلاصه : XSS یا CSS به حملاتی گفته می شود که مهاجم با وارد کردن کدهای html و Javascript و ... باعث اجرا شدن آن کدها در صفحه اجرایی خواهند شد و حتی با این روش می توان مستقیم یک سایت را هک کرد یا کوکی مدیر آن سایت را دزدید . بهتر است بعد از اینکه متغیری که از کاربران گرفته شد و قرار است محتوای آن متغیر نمایش داده شود از تابع Server.Htmlencode استفاده کنید .
 

elahi

مدیریت
مدیر کل انجمن
قدم ششم :

داشتم با یه نفر از طرفداران open source/php یه خورده اختلاط میکردم میگفتم چه خوب شد asp این باگهای php رو نداره . اگه داشت که مصیبت . register_global که پدر همه رو در اورده (میدونم register global باگ نیستاااا) . بعد file inclusion ، command execution . میدونستید با sql injection یا تزریق اطلاعات میشه در php یک فایل کامند شل درست کرد . بعد اون یارو میگفت اینا همش برتری php نسبت به asp هست که این توابع رو داره . گفتم فعلا که این برتری نصف بیشتر نویسنده های برنامه php رو داغون کرده . بعد همه درجه خطرشون بالا . اگر php این magic_gps رو نداشت الان باید تخته میکرد می رفت .

همه این ها رو گفتم که اگر با این باگها آشنایی دارین و یا فقط اسمشون رو شنیدید خودتون رو درگیر نکنید که فعلا asp از این باگها نداره . البته مثلا xp_cmdshell که با باگ sql injection در mssql اجرا میشه گفت خطرناک ولی این تیپی کسی کد مخرب ننوشته واسه برنامه های asp .
خلاصه اینکه اگه توی asp چند مورد که شاید به 20 تا هم نرسه رعایت کنید و اصول امنیتی کلی که ربطی به asp یا php نداره اون ها رو هم رعایت دیگه میتونید مطمئن به کار خودتون ادامه بدید .
این قسمت ادامه کار sql injection . ببخشید ضد sql injection (لول lol) .
همون طور که در پست های بالاتر اشاره شد برای متغیرهای عددی بی دردسرترین کار همون استفاده از تابع cint هست .
برای ما بقی متغیرها اگه علاوه بر ' جلوی سایر متغیر ها گرفته بشه ضرر نداره . ولی تا اونجایی که میدونم برای بانک اطلاعاتی access همین کافیه . برای ms-sql باید بیشتر احتیاط کنید .
name = replace(request.form("name") , "'","''")
name = replace(request.form("name") , "--","")
name = replace(request.form("name") , ";","")
select * from members where name = 'name'

و همچنین !@#$%^&*)(
اگر همین طور فیلتر کنیم سایر کاراکترهای !@#$%^&*)( بیایم پایین باز یه مشکلی داره کد بالا . البته خطری کسی رو تهدید نمیکنه ولی این نکته رو میگم که موقع کار با replace این موارد از دستتون در نره .
فرض کنید یکی name رو اینطوری مقدار دهی کرد .

member.asp?name= -;-

کد replace میاد ; رو بر میداره بعد هم چون -- ندیده دیگه این تکی ها رو فیلتر نمی کنه بعد name شما به این شکل در میاد :

name = --

توضیح : -- در mssql باعث می شود ما بقی عبارت SQL به اجرا در نیاید . کد مشابه آن در MySQL به این حالت است : */

گفتم زیاد فاجعه نیست ولی خیلی حملات از همین نکات جزیی است .

خلاصه : برای متغیرهای غیر عددی از تابع replace استفاده کنید و کاراکترهای ' و " و ; و -- و () و ... را فیلتر کنید .

دوستان انواع اشتباهات از قبیل فنی ، لغوی ، دیکته و ... بنده رو ببخشید . البته اشتباهات فنی / امنیتی رو نبخشید و مشکلی داره حتما بفرمایید که درست کنم . این که میبینید اکثر کدها به حالت شبه کده چون نمیخوام آموزش asp بدم به این حالت گذاشتم . جایی سوال بود مطرح کنید تا اونجا که بلد باشم جواب میدم .
 

elahi

مدیریت
مدیر کل انجمن
من Function برای تست کردن UserName به حالت زیر نوشتم که شکا هر کاراکتری را دوست دارین می تونین تویه Array اضافه کنید از نظر سرعت هم که خوب بود

private Function Check_Spel(Str_word)

Dim IntLen,Char_Not,Ch_Sel,Word
Dim i,j
Word = Str_Word
Char_Not = Array("","@","#","$","'","&","%","-")
IntLen = len(Word)
For i=1 to IntLen
Ch_Sel = Mid(Word,i,1)
For j=1 to UBound(Char_Not)
if Ch_Sel = Char_not(j) then
Check_Spel = ""
Exit Function
end if
next
next
Check_Spel = Word
End Function
 
بالا