Plain Text passwords
سلام
میخواستم امروز راجب shell بنویسم ، اما یه سری ادعا ها این چند روزه در مورد md5 و امنیتش شد که ترجیح دادم امرئز راجب امنیت پسورد ها بنویسم.
خوب بریم سر اصل مطلب:
امنیت در کلمات عبور:
کلمات عبور به صورت متن واضح و آشکار یا (Plain Text) :
خوب چیزی که واضح هست اینه که ما نباید کلمات عبور کاربران رو به صورت Plain Text در دیتابیس یا کوکی هامون ذخیره کنیم! چرا چون اگر کسی به دیتابیس یا کوکی دسترسی پیدا کنه اونوقت عملا کلمات عبور کاربران رو به راحتی بدست میاره و امکان ورودش با کلمه عبور کاربران به راحتی فراهم میشه!
اما راه حل چیه! راه حل اینکه کلمات عبور رو به این صورت داخل دیتابیس نریزیم استفاده از الگوریتم هایی هست به نام هشینگ یا هش کردن!
ابتدا اجازه بدید راجب الگوریتم های هش کمی با هم بحث کنیم:
برخلاف اون چیزی که تصور میشه الگوریتم های هشینگ ، در اصل الگوریتم رمز گذاری نیستند چون همونطور که میدونید الگوریتم های رمزگذاری
باید دو خاصیت رمزگذاری و رمزگشایی داشته باشن! به عبارت دیگه باید این امکان وجود داشته باشه تا از متن رمز شده به متن اصلی و از متن اصلی به متن رمز شده برسیم!
در صورتی که چنین امکانی در الگوریتم های هش وجود نداره! پس اول از همه یه اصطلاح رایج رو باید از این به بعد درست بیان کنیم چیزی به اسم رمز گذاری md5 یا sha1 وجود نداره بلکه باید گفت هش یا هشینگ md5 و sha1 !!!! نحوه کار الگوریتم های هش که دو نمونه قدرتمند اونها همون md5 و sha1 هیتند به این صورت هست که این الگوریتم ها میان به اضای هر تعداد کاراکتر حالا از یکی تا n تا کاراکتر به شما یه تعداد بیت مشخص داده میدن! مثلا md5 به اضای هر تعداد کاراکتری که بدید میاد بهتون 128 بیت برمیگردونه!
به این متن یا هش برگردونده شده میگن اثرانگشت یا fingerprint. دلیل این نام گذاری هم واضح هست در واقع مثل اثر انگشت انسان که در هر
شخص نسبت به دیگری متفاوت و به قول خودمون یکتاست این ها هم یکتا هستند!
به عبارت دیگه ! هیچ دو متنی نیستند که هش اونها برابر باشند مگر اینکه این دو متن در اصل یکی باشند! این الگوریتم ها ساختارشون به صورتی هست که عملا مهندسی معکوسشون غیر ممکن هست!
حالا بریم سر این موضوع که چه جوری کلمات عبور کاربران رو محافظت کنیم تا اصل کلمه عبور دست کسی نیفته!
چاره این کار استفاده از یکی از الگوریتم های پر کاربرد md5 و یا sha1 هست. خوشبختانه این دو الگوریتم در php پیاده سازی شدند و توابعی هم که این کار رو براتون میکنند به همین اسم هستند! یعنی md5() و sha1() .
شما باید کلمه عبور کاربر رو با یکی از این الگوریتم ها هش و در دیتابیس ذخیره کنید و از این به بعد هم کلمه عبور کاربر رو با همون الگوریتم هش و با ورودی کاربر برای کلمه عبور برابر قرار بدید تا اگر یکی بودن به کاربر اجازه ورود بدید!
مثال:
PHP:
$user_name = mysql_real_escape_string($_POST['username']);
$user_password = md5($_POST['password']);
$result = mysql_query('
SELECT COUNT(*) AS count
FROM users
WHERE user_name = "'.$user_name.'"
AND user_password = "'.$user_password.'"
');
$row = mysql_fetch_assoc($result);
if($row['count'] > 0) {
// Password is okay.
}
همونطور که دیدید دیگه لازم نیست md5 یا sha1 مربوط به کلمه عبور رو escape کنید چون هش همیشه یه عبارت آلفانامریک هست.
اما حالا میرسیم به یه جای جالب:
توی بعضی جا ها این ادعا میشه که الگوریتم های هش لو رفتن و بدرد نمیخورن در واقع چیزی که هست اینه که ادعا میکنن این الگوریتم ها قابل شکستن هستند و فلان سایت و برنامه هم برای اینکار وجود داره و این کار رو میکنه!
حالا یه توضیحی برای این دوستان میدم!
به این جور سایت ها دیکشنری md5 میگن! حالا چرا؟!!
حتما همتون با دیکشنری تا حالا کار کردید! دیکشنری معنای یه لغت رو توی یه زبون به به زبون شما میده!
مثلا hello به فارسی میشه سلام!!!
این سایت ها هم اومدن یه سری عبارات و حروف و ... که داشتن رو تبدیل کردن به md5 و اصل عبارت رو ریختن تو دیتابیسشون حالا اگر شما یه هش بهشون بدی که این هش رو تو دیتابیسشون داشته باشن به راحتی عبارت رو برمیگردونن!!!
مثلا فرض کنید یکی از این سایت ها بیاد تمام کلمات و عبارات به کار رفته تو یه دیکشنری مثل oxford رو ورداره و md5
هاش رو بریزه تو دیتابیسش و از یه طرف هم مثلا تا 12 رقم یه for بزاره و md5 اعداد رو بریزه تو دیتابیسش از این به بعد این سایت قادره
تمام کلمات عبوری که یه کلمه معنی دار در انگلیسی هستند و یا اینکه عددی کوچکتراز 12 رقم هستن رو براتون برگردونه! چون دایره لغت خودش رو انقدر گسترش داده!!!!
به عبارت دیگه این میشه یه دیکشنری md5 to english!!!
حتما همتون به این جور سایت ها سر زدید و دیدید که هر چیزی رو برنمیگردونن دلیل اون هم همین هست که در واقع تو دایره لغت اونها این عبارت هش شده وجود نداشته! و هرچیزی رو که بدونن برمیگردونن نه همه چیز!
پس از این هم میشه دلیل و مدعایی برای اینکه مطمئن باشید این الگوریتم ها قابل شکستن نیستند و این نوع کارها یه کاربرد سادست ار اون چیزی که بهش گفتیم اثرانگشت و هیچ ربطی به شکسته شدن الگوریتم نداره!!! اگر الگوریتمی قابل شکستن باشه دیگه فرقی نیمیکنه چی بهش بدی!!
پس از این به بعد به این سایت ها میگیم دیکشنری md5 !!!
خوب این نکات رو مشخص کردم تا از این به بعد با خیال راحت و مطمئن از اینکه این الگوریتم ها برگشت پذیر نیستند کار کنید!!!
اما بعد از این همه بحث در مورد هشینگ میرسیم به اینکه چه نکته هایی رو باید برای این که با این دیکشنری ها مقابله کنیم باید رعایت کنیم ! به عبارت دیگه از کجامطمئن شیم کاربر یه کلمه عبور تابلو انتخاب نمیکنه و اون کلمه قابل شناسایی برای این دیکشنری ها نیست!!!!
شما دو تا کار میتونید انجام بدید:
راه یا روش اول:
تو روش اول شما عوض اینکه کل 128 بیت هش شده رو تو دیتابیس بریزید میاید مثلا 10 یا 15 کاراکتر اون حالا کمتر یا بیشتر برحسب سلیقه خودتون
من به جای اینکه 5f4dcc3b5aa765d61d8327deb882cf99 رو بریزم تو دیتابیس
میام از هرجا دویت دارم یه تعداد کاراکتر رو جدا و اون رو میریزم تو دیتابیس مثلا میام:
5d61d8327deb882cf9
رو از هش جدا میکنم و به عنوان کلمه عبور کاربر درنظر میگیرم و از این به بعد هم بعد از ورود کلمه عبور توسط کاربر با همین عبارت بررسی میکنم و اگر درست بود بهش اجازه ورود میدم!
اگر این عبارت از رو کوکی یا دیتابیس لو بره چون عملا یه md5 نیست پس هیچ دیکشنری ای هم نمیتونه اصل عبارت رو برام برگردونه
و به این شکل هست که مطمئن میشم کاربرم اگر تابلو هم کلمه عبور ورداره قابل شناسایی نیست!!!
راه دوم استفاده از یه رشته هست که خودمون اضافه میکنیم!
درواقع میایم برای ذخیره کلمه عبور رشته خودمون رو به کلمه عبور کاربر اضافه و بعد هم هش اش رو میریزیم تو دیتابیس و از اون طرف هم
موقع لوگین باز این رشته رو به ورودی کاربر اضافه و هش ها رو با هم برابر میکنیم! اگر بود کاربر اجازه لوگین داره!
مثال:
چیزی که تو دیتابیس سیو میشه!
PHP:
$salt = 'thequickbrownfox';
$password 'foobar123';
$salted_hash = md5($salt . $password);
و موقع ورود کاربر
PHP:
$salt = 'thequickbrownfox';
$user_name = mysql_real_escape_string($_POST['username']);
$user_password = md5($salt . $_POST['password']);
$result = mysql_query('
SELECT COUNT(*) AS count
FROM users
WHERE user_name = "'.$user_name.'"
AND user_password = "'.$user_password.'"
');
$row = mysql_fetch_assoc($result);
if($row['count'] > 0) {
// Password is okay.
}
البته به جای thequickbrownfox بهتره از یه عبارت کاملا نامفهوم استفاده کنید مثل:
"s@aa#kkk%kk^()meacgdhjgdjfgj";
جملش که براتون مهم نیست
خیالتون راحت هیچ چیز و هیچ کسی نمیتونه عبارت اصلی رو بهتون برگردونه!! و ادعای شکستن یا لو رفتن md5 یه چیز دروغی و خنده دار بیش نیست پس گول نخورید و الکی هم حرص نخورید!!!!
از نظر امنیت الگوریتم sha1 باز هم نسبت به md5 از امنیت بالاتری برخورداره و تعداد بیتی که برمیگردونه 160 بیت هست! من خودم بیشتر از sha1 استفاده میکنم! البته جاهایی که توچشم هست عبارت برا دیتابیس از همون md5 استفاده میکنم!
موفق باشید