PDA

View Full Version : آموزش: چگونگی Login کاملا امن در HTTP



flashswf
یک شنبه 06 مهر 1393, 23:30 عصر
این مقاله برای اولین بار جهت استفاده در سایت barnamenevis.org ارائه گردیده است و هر گونه استفاده از آن فقط با ذکر منبع و نام نویسنده بلامانع می باشد.

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

چگونگی Login کاملا امن در HTTP

مقدمه
همان طور که می دانید تمام اطلاعاتی که از طریق پورت HTTP منتقل می شود قابل رهگیری و خواندن است و توسط هر ISP ، و شخصی قابل مانیتور کردن است.
در حالت کلی اطلاعاتی که از طریق این پوروتوکل انتقال داده می شود از اهمیت چندانی برخوردار نیستند مثل اطلاعات معرفی یک شرکت ،سایت ،اطلاعات محصول و ... ولی در مواردی این اطلاعات بسیار مهم و حیاتی هستند و مانیتور کردن آنها توسط یک هکر می تواند بسیار خطرناک باشد مثل اطلاعات حساب بانکی و... که در این موارد باید از SSL(HTTPS) استفاده کرد. در مواردی اطلاعات خیلی حیاتی هستند در صورتی که دسترسی به SSL امکان پذیر نبوده و یا هزینه آن مرقوم به صرفه نیست در این شرایط در موارد خاص می توانیم این امنیت را بر روی HTTP نیز برقرار نماییم برای مثال Login کردن اعضا و عضویت آنها در وب سایت یکی از این موارد است.
مهمترین عنصر درفرایند Login و عضویت کاربر وجود فیلد، Password است که اگر توسط یک هکر مانیتور شود به راحتی می تواند به حساب کاربر Login وارد شود. در این قسمت اطلاعاتی مانند نام کاربری از اهمیت خاصی برخوردار نیستند.
در نتیجه در عضویت و ورود یک عنصر حیاتی وجود دارد و آن Password کاربر است. چگونه می توانیم امنیت Password را در پروتوکل HTTP برقرار نماییم؟

ذخیره Password در بانک اطلاعاتی
همان طور که می دانید بهتر است همیشه Password را برای ذخیره در بانک اطلاعاتی رمز نگاری کنیم تا در صورتی که شخصی بتواند به اطلاعات بانک اطلاعاتی شما دسترسی پیدا کند نتواند Password کاربران سایت یا برنامه شما رو پیدا کند و وارد سایت یا نرم افزار شما شود.
از چه روشی رمزنگاری برای ذخیره Password در بانک اطلاعاتی استفاده کنیم؟
همان طور که می دانید پیچیده ترین روش های رمز نگاری قابل بازیابی هستند و اطمینان 100% به آنها وجود ندارد و حتی اگر این اطمینان وجود داشته باشد درصورتی که کلید رمزنگاری فاش شود می توان اطلاعات را از رمز خارج کرد.
حال چه باید کرد؟
بهترین روش رمزنگاری برای اطلاعاتی که نیازی به خواندن متن کامل آن وجود ندارد و فقط جهت مقایسه از آنها استفاده می شود مانند Password استفاده از الگوریتم های Hash(رمزنگاری یکطرفه) است بدین معنی که Password شما فقط قابل تبدیل به کد رمزنگاری شده بوده و به هیچ عنوان قابل بازگشت به متن عادی را نخواهد داشت این موضوع به شما این ضریب اطمینان را میدهد که اگر شخصی به اطلاعات بانک اطلاعاتی شما دسترسی پیدا کرد به Password کاربران دسترسی نداشته باشد.

از چه نوع الگوریتمی استفاده کنیم؟
در این مقاله به طور مشخص از الگوریتم Hex Hash MD5 استفاده شده که سایت های زیادی از آن برای ذخیره کلمه عبور و Login کاربران استفاده میکنند مانند Yahoo ، vBulletin ، Jomla و ... که نمونه این پیاده سازی را در آدرس زیر می توانید مشاهده نمایید.
http://www.md5hashgenerator.com
در زیر پیاده سازی این الگوریتم در سه زبان مختلف ارائه شده و پیاده سازی های زبان های دیگر را با جستجو یی ساده می توانید پیدا نمایید.

JavaScript (http://pajhome.org.uk/crypt/md5/): http://pajhome.org.uk/crypt/md5/
C# (http://www.codeproject.com/Articles/21312/Generating-MD5-Hash-out-of-C-Objects):http://www.codeproject.com/Articles/21312/Generating-MD5-Hash-out-of-C-Objects
PHP (http://php.net/manual/en/function.md5.php): http://php.net/manual/en/function.md5.php


چگونگی استفاده از Hash MD5
در هر زبان برنامه نویسی با توجه توضیحات و متد ارائه شده در آن زبان می توان از این رمزنگاری استفاده نمود که در این مقاله نحوه استفاده از آن در زبانهای JavaScript و C# توضیح داده شده است.

چگونگی Login با استفاده از Hash MD5
به صورت پیش فرض مقاله ما Password کاربر را به صورت Hash MD5 در بانک اطلاعاتی ذخیره نموده ایم و هم اکنون قابل بازیابی نیست در این حالت می توانید به روش زیر Login امنی در HTTP داشته باشید.
چنان چه گفته شد در پروتوکل HTTP تمامی اطلاعات قابل رهگیری و بازیابی است پس برای اینکه Password در انتقال از کلاینت به سرور فاش نشود باید Password را قبل از ارسال به سرور در کلاینت به کد Hash MD5 تبدیل نماییم سپس اطلاعات را به سرور انتقال دهیم برای این کار به شکل زیر عمل میکنیم:


Password را با استفاده از کلاس JavaScript که در بالا عنوان شد با متد hex_md5 از فیلد Password بهHash MD5 تبدیل و در فیلد Hidden به اسم MD5 ذخیره میکینم.
مقدار فیلد password را خالی میکنیم تا Password هش نشده به سرور انتقال پیدا نکند.
فرم رو برای سرور پست میکینم.
در سرور مقدار فیلد MD5 را با Passwordی که قبلا در بانک اطلاعاتی به صورت Hash MD5 ذخیره نموده ایم مقایسه و اگر صحیح بود Login میکنیم.

کد HTML این مثال در زیر آمده است.


<head> <script type="text/javascript" src="http://pajhome.org.uk/crypt/md5/2.2/md5-min.js"></script> <script type="text/javascript"> function hashPassword() { document.getElementById("MD5").value = hex_md5(document.getElementById("password").value); document.getElementById("password").value = ""; } </script></head><body> نام کاربری:<input type="text" id="userName" /><br /> کلمه عبور:<input type="password" id="password" /><br /> <input type="hidden" id="MD5" /> <input type="submit" id="login" value="ورود" onclick="hashPassword()" /></body>

نکته:


در کد بالا اگر هکر به هنگام انتقال اطلاعات از کلاینت به سرور به Password کاربر دسترسی پیدا کند فقط Passwordی که Hash شده است را خواهد دید و Password اصلی کاربر را نخواهد داشت.
کد بالا مشکلی نیز دارد و آن اینکه درست است که هکر Password کاربر را ندارد اما در صورتی که به صورت دستی فیلد MD5 که hidden است را با مقدار Hash که در هنگام مانیتور کردن HTTP به دست آورده جایگزین نماید خواهد توانست Login نماید.

راه حل چیست و چگونه می توان ورودی کاملا امن داشت؟

طریقه Login امن با استفاده از Hash MD5 و کلید خارجی
در روش بالا ورود کاملا امن نبوده و هکر همچنان می تواند بدون داشتن Password اصلی وارد سیستم شود پس چگونه ورودی کاملا امن داشته باشیم.
برای اینکار نیاز به یک کلید خارجی داریم که توسط سرور به شکل تصادفی ایجاد شود و در هر مرتبه ورود کاربر متغییر باشد از این کلید و Hash MD5 که توسط متد hex_md5 ایجاد شده یک Hash MD5 جدید ایجاد می نماییم که در هر بار ورود کاربر متفاوت خواهد بود.
این کلید می بایست متغییر بوده و به راحتی قابل دسترس باشد که در این مقاله از Session ID کاربر استفاده میکنیم.


Session ID کاربر را دریک فیلد Hidden به اسم SID برای کلاینت ارسال می کنیم.
Password را با استفاده از کلاس JavaScript که در بالا عنوان شد با متد hex_md5 از فیلد Password بهHash MD5 تبدیل و در فیلد Hiddenی به اسم MD5 ذخیره میکینم.
مقدار فیلد MD5 را با مقدار فیلد SID جمع و نتیجه حاصله را با متد hex_md5 بهHash MD5 جدیدی تبدیل و در فیلد MD5 ذخیره میکینم.
مقدار فیلد password رو خالی میکنیم.
فرم را برای سرور پست میکینم.
در سرور Passwordی که قبلا در بانک اطلاعاتی به صورت Hash MD5 ذخیره کرده ایم را با Session ID کاربر جمع و نتیجه را Hash میکنیم و با مقدار فیلدMD5 مقایسه می کنیم اگر درست بود Login میکنیم.

در این حالت کد MD5 ایجاد شده در هر دفعه ورود کاربر متفاوت خواهد بود و هکر با داشتن این کد نمی تواند وارد سیستم شود.
کد HTML این مثال در زیر آورده شده:



<head>

<script type="text/javascript" src="http://pajhome.org.uk/crypt/md5/2.2/md5-min.js"></script>

<script type="text/javascript">

function hashPassword() {

document.getElementById("MD5").value = hex_md5(document.getElementById("password").value);

document.getElementById("MD5").value = hex_md5(document.getElementById("MD5").value + document.getElementById("SID").value);

document.getElementById("password").value = "";

}

</script>

</head>

<body>

نام کاربری:<input type="text" id="userName" /><br />

کلمه عبور:<input type="password" id="password" /><br />

<input type="hidden" id="SID" value="1ux1rumvu15irfbx1eqjew55" />

<input type="hidden" id="MD5" />

<input type="submit" id="login" value="ورود" onclick="hashPassword()" />

</body>


چند نکته:


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

در زیر کد آخرین مثال با زبان C# در ASP.NET آورده شده است:



<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">

protected void Submit_Click(object sender, EventArgs e)
{
//نام کاربری موجود در بانک اطلاعاتی
string DB_userName = "admin";
// کلمه عبور هش شده در بانک اطلاعاتی
string DB_hashPassword = "827ccb0eea8a706c4c34a16891f84e7b";
//مقایسه نام کاربری و کلمه عبور با استفاده از سشن آی دی
if (MD5.Value == HashMD5(DB_hashPassword + Session.SessionID)
&& DB_userName == userName.Text.ToLower())
{
result.Text = "ورود موفقیت آمیز";
}
else
{
result.Text = "نام کاربری یا کلمه عبور اشتباه است";
}
}
protected void Page_Load(object sender, EventArgs e)
{
//وجود این خط برای این است که در دات نت باید از سشن استفاده شود تا مقدار سشن آی دی ثابت گردد
Session["init"] = 0;
//ارسال مقدار سشن آی دی به کلاینت
SID.Value = Session.SessionID;
}
//فانکشن تبدیل کلمه عبور به کد هش
protected string HashMD5(string password)
{
byte[] BytPass = System.Text.Encoding.UTF8.GetBytes(password);
System.Security.Cryptography.MD5CryptoServiceProvi der md5 =
new System.Security.Cryptography.MD5CryptoServiceProvi der();
byte[] result = md5.ComputeHash(BytPass);
string hash = "";
foreach (byte a in result)
{
if ((a < 16))
{
hash += "0" + a.ToString("x");
}
else
{
hash += a.ToString("x");
}
}
return hash;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>چگونگی ورود کاملا امن در HTTP</title>
<style type="text/css">
body, input
{
font: 11px tahoma;
direction: rtl;
}
</style>
<script type="text/javascript" src="http://pajhome.org.uk/crypt/md5/2.2/md5-min.js"></script>
<script type="text/javascript">
function hashPassword() {
document.getElementById("MD5").value = hex_md5(document.getElementById("password").value);
document.getElementById("MD5").value = hex_md5(document.getElementById("MD5").value + document.getElementById("SID").value);
document.getElementById("password").value = "";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:TextBox ID="userName" runat="server"></asp:TextBox><br />
<asp:TextBox ID="password" runat="server" TextMode="Password"></asp:TextBox><br />
<asp:HiddenField ID="MD5" runat="server" />
<asp:HiddenField ID="SID" runat="server" />
<asp:Button ID="Submit" runat="server" Text="ورود" OnClientClick="hashPassword()" OnClick="Submit_Click" /><br />
<asp:Label ID="result" runat="server" Text=""></asp:Label>
</form>
</body>
</html>



مثالهای این مقاله به صورت پیوست قابل دریافت می باشد.123989

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

نویسنده: مهدی دهگر منفرد
رایانامه: flashswf [A t] gmail.com