PDA

View Full Version : بحث درمورد سالت رندوم به ازای هر کاربر و ذخیرهء آن در دیتابیس



eshpilen
یک شنبه 02 بهمن 1390, 12:23 عصر
باشه بعد میام و ادامه میدم...
فعلا خیلی وقت صرف کردم و خسته شدم.
شما هم برو نهارت رو بخور.
احتمالا نمیخوایم چند روز تمام وقت و انرژی خودمون رو هم صرف این بحث کنیم! پس عجله نکنید.
منکه چنتا مقالهء ویکیپیدا در زمینه های دیگه باز کردم از صبح همینطوری موندن و وقت نکردم بخونم.
حالا غذا و ورزش و تفریح و خواب و پول تلفن و اینترنت به کنار!!
چشم و چالمون هم که درآمد!

MMSHFE
یک شنبه 02 بهمن 1390, 12:31 عصر
باشه عزیز. میگم ADSL مخابرات بگیر راحت بشی! :چشمک:
من هم دارم یک مقاله درمورد ترکیب hash و encryption برای بالارفتن امنیت میخونم، بد نیست. نتیجه رو توی همون بحث ذخیره امن پسورد کاربران میگذارم. موفق باشید.

eshpilen
یک شنبه 02 بهمن 1390, 12:36 عصر
ببین عزیزم بیخود بحث رو قاطی و پیچیده نکن. مطلب گسیخته میشه.
بحث در این تاپیک تحلیل یک روش جدید نیست.
در اینجا فقط میخوایم این ادعا رو که سالت رندوم به ازای هر کاربر و ذخیرهء اون در دیتابیس چه خاصیت و فایده ای داره یا نداره بررسی کنیم.
شما میخوای واسه مطلب خودت یک تاپیک جداگانه استارت کن.
در اینجا روی موضوع بحث خودمون تمرکز میکنیم.
آهان اون یکی تاپیک رو گفتی؟
بنده این آزادی رو از کسی نمیگیرم، ولی بنظر من اون بحث و مطالب آموزشی رو با این کار خراب میکنی.
دوست داشتی این کار رو بکن.
بهرحال بنظر من یک تاپیک مجزا براش ایجاد کن.
چون هرکدام از این بحثها و سیستمها جدا هستن و هرکدام کلی توضیح و تحلیل جداگانه میخوان.
همینطوریش ملت متوجه نمیشن، اونوقت با ده تا طرح و چیز دیگه هم قاطیش کنیم؟! هنوز اون بحث در حد مقدمات بود و به جایی نرسیده بود که وسطش میخوای یه سیستم دیگر رو مطرح و مقایسه کنی.

MMSHFE
یک شنبه 02 بهمن 1390, 12:57 عصر
اوکی! بابا چرا قاطی میکنی؟ باشه نمیگذارمش. اگه دیدم سودمنده، بحث جداگانه ای براش ایجاد میکنم. سکته میکنی ها!

eshpilen
یک شنبه 02 بهمن 1390, 14:45 عصر
البته جای ذخیره کردن خیلی مهمه. اگه توی دیتابیس باشه، عملاً وجود سالت رندوم هیچ دردی رو دوا نمیکنه چون وقتی هکر به دیتابیس دسترسی پیدا کرد، سالت رو هم داره و میتونه رشته رو حتی راحتتر از حالتی که سالت ثابت داریم ولی در اختیار هکر نیست، رمزگشایی کنه.ما الان یک سیستمی رو فرض میکنیم که هم سالت رندوم داره و هم سالت ثابت.
سالت رندوم رو در دیتابیس ذخیره میکنیم، و سالت ثابت رو در جای دیگری (مثلا در سورس برنامه).
البته سالت ثابت بنظرم اصطلاح صحیحی نیست از نظر فنی و حداقل میتونه مبهم باشه، ولی ما برای راحتی خودمون و شما ازش استفاده میکنیم.

سالت ثابت ما اسمش مثلا pepper باشه.

اطلاعات دیتابیس ما به این شکله:

user1 salt1 hash1
user2 salt2 hash2
user3 salt3 hash3
...

هش های ما با این فرمول تولید شدن:

$hash_n=md5($pepper.$salt_n.$password_n)

منظور از _n یعنی همون شماره ها که در بالا میبینید. یعنی هش کاربر ان ام، سالت کاربر ان ام، پسورد کاربر ان ام.
نکته: استفاده از md5 فقط بخاطر سادگی مثال و آشنایی همگانی هست و ما در شرایط واقعی از این تابع ضعیف استفاده نخواهیم کرد.

حالا هکر میاد و دیتابیس رو میخونه، ولی نتونسته سالت ثابت رو بدست بیاره.
در این صورت هکر قادر نیست هیچ پسوردی رو روی هش های دیتابیس تست کنه.
چون مثلا میخواد هش پسوردی مثل love رو تست کنه، باید اول pepper رو داشته باشه تا بتونه هش صحیحی رو که سیستم ما با چنین پسوردی تولید میکنه بدست بیاره و بعد اون رو با هشهای ثبت شده در دیتابیس مقایسه کنه.
پس، نتیجه میگیریم که تاوقتی هش ثابت بدست هکر نیافتاده، با داشتن تمام محتویات دیتابیس ما بازهم نمیتونه پسوردهای اولیهء کاربران رو کشف کنه.
نتیجه ای که حاصل میشه اینه که، نیازی نیست تمام سالت ها رو در جایی غیر از دیتابیس ذخیره کنیم. چون اگر جای امن تری برای ذخیرهء اطلاعات داشته باشیم، ذخیرهء فقط سالت ثابت در اون مکان برای ناتوان کردن هکر در کرک هش ها کافیه، و اگر هکر به اون مکان دسترسی پیدا کنه طبیعتا هردوی هش ثابت و هش های رندوم رو بدست خواهد آورد و وضعیت هیچ فرقی نمیکنه.

پس این یک موضوع. فکر میکنم ثابت شده باشه و قبول کرده باشید چون خیلی روشن و ساده هست. نیازی به کد و تست واقعی نداره، ولی اگر واقعا متوجه نشدید و نمیخواید فقط وقت و انرژی بنده و دیگران رو تلف کنید، بفرمایید تا مثال هم براتون بذارم.

خب حالا میریم وضعیتی رو بررسی میکنیم که هکر هردوی دیتابیس و سالت ثابت رو بدست آورده.

در این صورت هکر میتونه هش پسورد love رو به ازای هر اکانت محاسبه کنه.
بطور مثال اگر سالت ثابت ما xmsopHrteyDss472 و سالت اکانت user1 برابر emroUaqw423XXmaqz باشه، هکر هش love رو به این شکل محاسبه میکنه:

echo md5('xmsopHrteyDss472'.'emroUaqw423XXmaqz'.'love') ;
که جوابش میشه: ce752ec7e18178e8b1182a37f60a11f7
حالا هکر (یا درواقع برنامهء خودکارش) این مقدار رو با هش user1 مقایسه میکنه. اگر هش یکسان بود یعنی پسورد کاربر love است و اگر نبود یعنی معلوم نیست.
اما حالا فرضا پسورد user2 دقیقا همین love باشه. آیا هش اون با این هش یکی هست؟
جواب واضحا خیر هست. چون سالت رندوم اون کاربر که در محاسبهء هش دخیل هست متفاوت است از هش کاربر اول که ما برای محاسبهء این هش بکار بردیم.
فرضا سالت رندوم user2 برابر wuoi344xhdpq0DDkL هست.
محاسبهء:

echo md5('xmsopHrteyDss472'.'wuoi344xhdpq0DDkL'.'love') ;
منجر به هش کاملا متفاوت e246b6bf787b18f4c045c88109b038ef میشه.

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

اما اگر سالت متفاوت به ازای هر کاربر رو نداشتیم، نتیجهء محاسبهء:

echo md5('xmsopHrteyDss472'.'love');
برابر 4272d5eaa7006541751d60380e8df0be میشد که هرکدام از اکانتها اگر پسورد love داشتن چنین هشی در رکورد دیتابیس اونها مشاهده میشد. چون تنها ورودی این هش، سالت ثابت و پسورد love هست که خروجی اون وابسته به اینکه روی اکانت کدام کاربر اون رو تست میکنیم نداره.

بنابراین اگر سالت رندوم به ازای هر کاربر وجود نداشت، و دیتابیس ما فرضا 1000 کاربر داشت، و هکر میخواست صدهزار پسورد رو روی هر اکانت چک کنه، و هر عملیات تولید هش روی رایانهء هکر 1 هزارم ثانیه طول میکشید، زمان مورد نیاز برای این حمله:

100000*0.001=100
100 ثانیه یا تقریبا یک و نیم دقیقه وقت لازم میبود.
چون نیاز بود هر هش فقط یک بار محاسبه بشه و به تعداد اکانتها وابسته نبود.
البته ما زمانهای لازم برای بقیهء عملیات و مقایسه و اینطور چیزها رو حساب نکردیم. چون فقط میخوایم تفاوت زمانی رو که سالت رندوم به ازای هر کاربر اضافه میکنه محاسبه کنیم.

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

100000*0.001*1000=100000
و این یعنی هزاربرابر زمان بیشتر؛ صدهزار ثانیه نزدیک به 28 ساعت.

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

شاید بگید زمان 1 میلی ثانیه برای یک هش md5 خیلی زیاده. بله، اما اولا ما از md5 استفاده نمیکنم و از توابع هش جدیدتر و امن تری که کندتر هستن استفاده میکنیم، دوما از روش key stretching هم استفاده میکنیم تا زمان لازم برای محاسبهء هر هش رو افزایش بدیم. در روش key stretching عملیات هش هزاران بار تکرار میشه.
بطور مثال این کدی هست که در یک بخش از phpass (http://www.openwall.com/phpass/)-0.3 برای همین کار بکار رفته:

$hash = md5($salt.$password);
do {
$hash = md5($hash.$password);
} while(--$count);
یعنی عملیات هش رو در یک حلقه به تعدادی تکرار میکنه و هش نهایی حاصل ترکیب هش تمام دورهای این حلقه هست.
شما باید تعداد دورها و زمان هر هش رو مقداری تنظیم کنید که با توجه به ترافیک حال حاضر و قابل پیشبینی برای آینده، مشکلی جدی ای از نظر بار پردازشی ایجاد نکنه و برای کاربران هم خیلی مشهود و آزار دهنده نباشه. مثلا در یک سایت معمولی که ترافیک سنگینی نداره، این مقدار میتونه حتی تا چند دهم ثانیه هم برسه.

فرضا اگر کاری کنید که هر هش 1 دهم ثانیه زمان صرف کنه، زمان حملهء هکر در مثال فرضی بالا صدبرابر میشه؛ یعنی 116 روز طول میکشه تا هکر بتونه حملهء خودش رو کامل کنه! اونم فقط با صدهزار پسورد که یک حملهء دیکشنری کوچکی بیش نیست. حمله های خیلی قویتر و گسترده تر از این وجود دارن که بدون بکارگیری این روشهای جلوگیری ممکن هستند اما با این روشها غیرممکن میشن (حتی با زمانهای پردازش خیلی کمتر از 1 دهم ثانیه برای هر هش). خیلی از حمله های محدودتر هم حداقل از دسترس بیشتر افراد و هکرهای عادی خارج میشن یا دیگه براشون از نظر زمان و پول مورد نیاز صرف نمیکنه.

درسته بعضی هکرها میتونن از رایانه های زیاد یا منابع پردازشی برابر با هزاران رایانهء عادی استفاده کنن، اما بهرحال طول و تعداد پسوردهای قابل انتخاب اونقدری زیاده که اونا هم نمیتونن هش هر پسوردی رو کرک کنن. اگر کرک هر هشی به این سادگی بود که اینهمه الگوریتم و پروتکل رمزنگاری که بر مبنای هش عمل میکنن امنیت نداشتن و شکسته میشدن. کاری که شما با سالت و key stretching میکنید اینه که محدوده/تعداد پسوردهای قابل تست و کرک برای هکرها رو خیلی کوچکتر میکنید و بنابراین پسوردهای خیلی کمتری توسط هکرها قابل تست و کرک خواهند شد و در نتیجه یکسری پسوردهایی که قبلا اونقدری ضعیف بودن که با این حمله ها کشف بشن اما خیلی هم ضعیف نبودن که با چند هزار و چند صدهزار و چند میلیون برابر کردن پردازش مورد نیاز برای تست هر پسورد روی همهء اکانت ها کشف بشن، حالا در محدودهء کم و بیش امنی قرار میگیرن و هکر نمیتونه به تست کردن اونها برسه، چون قبلش باید میلیونها و میلیاردها ترکیب پسورد احتمالی دیگر رو با صرف زمان و هزینهء خیلی زیادی تست کنه. و این قضیه درمورد پسورد کاربران کاملا موثر هست، شما نمیتونید امنیت پسوردهای خیلی ضعیف رو به اطمینان بالایی برسونید که بگید قابل کرک نیستن (چون اینا رو با حدس و دیکشنری های کوچک از متداول ترین پسوردها یا Brute-force در محدوده های کوچک میشه کرک کرد)، اما امنیت پسوردهایی که اونقدرها هم ضعیف نباشن رو میتونید به حد بسیار خوبی برسونید. پسوردهای خیلی قوی هم که بهرصورت امن هستند، چون اینقدر تعداد حالتهایی ممکن برای رسیدن به اونها زیاده که بشر چنین قدرت پردازشی ای رو در اختیار نداره و تا آیندهء نزدیک هم پیشبینی نمیشه به چنین توان پردازشی ای برسه.

H:Shojaei
یک شنبه 02 بهمن 1390, 21:27 عصر
سلام دوست عزیز
مقاله ی جالبی بود واقعا استفاده کردم mer30
در حقیقت شما با ترکیب چند رشته که تشکیل شده از پسورد کاربر و سالت رندم و سالت ثابت است و تکرار به اندازه ی کافی یک password کاملا غیر نفوذ ساختید
درسته اگه تو درک من از نوشته های شما مشکلی هست لطفا بفرمایید چون خیلی زیاده دوباره نمیتونم بخونم:گیج:
mer30

eshpilen
یک شنبه 02 بهمن 1390, 22:43 عصر
ما کاری کردیم که عملیات کشف پسورد اولیه از روی هش ها بسیار بسیار زمان‌برتر بشه. نمیشه گفت در تمام موارد تمام پسوردها غیرقابل نفوذ میشن.

طبیعتا یک پسورد خیلی ضعیف هنوز هم آسیب پذیره و ممکنه کشف بشه، ولی ما با ترکیب متد سالت رندوم به ازای هر اکانت و متد key stretching کاری کردیم که تعداد پسوردهایی که کرکرها میتونن تست کنن بسیار بسیار کمتر بشه. فرضا اگر قبلا اینقدر توان پردازشی و زمان مقرون به صرفه در اختیار داشتن که میتونستن حداکثر یک میلیارد پسورد رو روی اکانتهای کاربران ما تست کنن، الان با سیستم تقویت شدهء ما میتونن تنها ده هزار پسورد رو تست کنن. خلاصه حداکثر ممکن براشون هرچقدر باشه، با یک ضریب بسیار زیاد کاهش پیدا میکنه.

اگر قبلا به یک سال وقت برای کرک کردن یک دیتابیس مهم توسط یک حملهء Brute-force بسیار گسترده نیاز داشتن و این زمان براشون صرف میکرد، الان زمان مورد نیاز برای همون حمله صدهزار برابر شده!! و طبیعتا این خیلی خیلی موثر و اهمیتش غیرقابل تردیده. چون دیگه هکرها نمیتونن تعداد خیلی بالایی پسورد رو روی تعداد زیادی اکانت تست کنن و بنابراین پسوردهای خیلی کمتری کرک خواهند شد. پسوردهای واقعا ضعیف کرک میشن. مثل همون love که مثال زدیم. love فقط برای سادگی مثال و انجام محاسبات بود، نه اینکه بخوام بگم چنین پسورد درپیتی رو میشه با این سیستم ایمن کرد. نه یکسری پسوردهایی از این قویتر باید باشن. اکثر سیستمها پسورد کوتاهتر از 6 یا 8 کاراکتر رو قبول نمیکنن.

در همین مثالهایی که زدم و میتونن کاملا واقعی باشن، ما زمان لازم برای عملیات کرک رو صدهزار برابر افزایش دادیم!

البته نقش سالت ثابت هم در اینجا این بود که در هک هایی که هکر دیتابیس رو میخونه اما دسترسی به فایلها نداره، نمیتونه حمله ای رو جهت کرک کردن پسوردها صورت بده، چون بخشی از اطلاعات مورد نیاز جهت تولید هش ها رو در اختیار نداره. اما نباید فرض کرد که سالت ثابت به هیچ وجه قابل دسترسی هکرها نیست. وقتی سایت رو دیفیس میکنن یعنی دسترسی کافی دارن و میتونن فایل آپلود یا ویرایش کنن، پس میتونن وبشل کار بذارن یا اصلا با استفاده از همون PHP کدهای لازم برای خوندن سالت ثابت ما رو نوشته و اجرا کنن. اگر برنامهء ما این کار رو میکنه، برنامهء هکر هم میتونه، فقط هکر باید بتونه دسترسی نوشتنی به www پیدا کنه. اونوقت اگر ما سالت رندوم به ازای هر اکانت و key stretching نداشته باشیم، ظرفیت کرک هش ها توسط هکر بسیار زیادتر خواهد بود.