زمانی که ادوب اعلام کرد پسوردهای رمز شده لو رفته اند سوال پیش اومد که این پسوردها رمز شده بودند یا هش؟
اصطلاح رمز شده یا Encrypted زمانی استفاده می شه که امکان Decrypt هم باشه، ینی ادوب بتونه پسورد شما رو به صورت واضح بخونه در حالیکه روش امنی که باید برای نگهداری پسوردها استفاده بشه هش Hash کردنه که یک طرفه است و از نتیجه هش نمی شه به پسورد اصلی رسید. برای بالا بردن امنیت پسوردهای ذخیره شذه از salt هم استفاده می شه که یک رشته از کراکترهای تصادفیه که پیش از هش شدن به پسورد اضافه می شه. استفاده از salt باعث می شه که اگر دو کاربر از پسورد مشابهی استفاده کرده باشند، نتیجه هش شده برای اونها متفاوت می شه و درنتیجه در صورت دسترسی هکر به دیتابیس، پیداکردن پسورد مشکلتر می شه.
بذارید یه نگاهی به دیتابیس ادوب و پسوردهای کاربرها بندازیم. این بررسی بر روی ۱ میلیون ردیف اطلاعات انجام شده. این مجموعه به صورت خطی جدا شده: ضرایب ۱۰. لیست انتخابی یه چیزی شبیه تصویر زیر می شه.
و در تصویر زیر می بینید که اطلاعات هر ستون مربوط به چه فیلدی است.
این فیلدها برای بررسی ما غیر ضروری بود و حذف شدند: user ID, email addresses, username
فقط ستون های پسورد و یادآوری باقی موندن. همچنین پسوردها نیز با روش base64 رمزگشایی شدن و به نسخه هگزادسیمال تبدیل شدند. با این تبدیل طول پسوردها واضح تر شد:
سوال اینه که آیا ادوب راست گفت که پسوردها رمز شده بودند؟ می دونیم که نتیجه پسوردهای هش شده، طول یکسانی دارند و ربطی به تعداد کاراکترهای پسورد نداره. مقایسه طول پسوردهای ادوب نشون می ده که اونها هش نشده اند.
سوال بعدی اینه که حالا که پسوردها هش نشدن پس از چه روش رمزگذاری (Encryption) استفاده شده؟ روش هایی مثل RC4 یا Salsa-20 رو کنار بذاریم چون نتیجه رمزگذاری در این دو روش با طول پسوردها برابر می شه. در حالیکه در تصویر بالا می بینیم که پراکندگی طول پسوردهای رمز شده مخالف اینه.
Stream cipher که به طور معمول در پروتوکول های شبکه استفاده می شه به ما اجازه می ده که هر بار یک بایت از اطلاعات رو رمز کنیم بدون اینکه مجبور باشیم ورودی را به تعداد مشخصی بایت بلوک بندی کنیم.
با توجه به اینکه رمزها ضریبی از ۸ است مشخصا دنبال روش رمز گذاری می ریم که بلوک های ۸ بایتی (۶۴ بیت) رو رمز گذاری می کنه. در نتیجه به نظر میاد که با یک روش رمزگذاری DES (Data Encryption Standard) و یا نسخه مدرن ترش ۳DES طرفیم. (این احتمالات رو کنار گذاشتیم: سایر روش های ۶۴ بیتی که یه زمانی استفاده می شدند و یا شیوه جدیدی ساخته خود ادوب)
این شیوه رمز گذاری متقارن،اگر حد سما درست باشه، به طرز حیرات انگیزی اشتباهه چرا که هم غیر ضروریه و هم خطرناک. هر کسی که کلید رمزگذاری رو محاسبه کنه، حدس بزنه و یا کش بره می تونه به همه پسوردهای دیتابیس دسترسی داشته باشه. از سوی دیگر با هش کردن می شه هر پسورد رو به صورت مجزا ایمن کرد و هیچ کلیدی نمی تونه همه پسوردها رو به حالت خوانا بر گردونه. این روشیه که سیستم های مبتنی بر یونیکس ۴۰ ساله که دارن استفاده می کنند.
سوال بعدی اینه که از چه مدی برای رمزگذاری (encryption mode) استفاده شده.
ابتدایی ترین مدی که برای رمزگذاری استفاده می شه “مد رمز گذاری بلوکی خام”ه که با اسم Electronic Code Book (ECB) شناخته می شه. در این حالت الگوهای متن اولیه در متن رمزگذاری شده قابل شناساییه. در مدهای دیگه این ضعف وجود نداره و الگوها رو غیر قابل شناسایی می کنند.
یکی از دلایلی که از ECB استفاده نمی شه اینه که نتیجه رمز گذاری یک پسورد ثابت با یک کلید ثابت و با این مد، نتیجه یکسانی رو به همراه داره. بذارید یه نمونه تصویری از این مشکل رو ببینیم.
فرض کنیم تصویر کلمه sophos رو با ترکیب رنگ RGB داشته باشیم (که هر پیکسل ۳ بایت داره) و اون رو به بلوک های ۸ بایتی تقسیم کنیم و با روش DES و مد ECB اون رو رمزگذاری کنیم. حال با فایل به دست اومده به عنوان یک تصویر RGB برخورد کنیم و اون رو نگاه کنیم، نتیجه زیر حاصل می شه
مدهایی که الگوی متن رو استتار می کنند به چیزی بیش از یک کلید احتیاج دارند. اونها nonce (عددی که یک بار استفاده شود) به کار می برند. nonce در ترکیب با کلید و متن اولیه باعث می شه که هر بار رمزگذاری، خروجی منحصر به فرد داشته باشه.
اگر ادوب از این روش استفاده می کرد می بایست در کوتاه ترین پسورد شاهد ۱۶ بایت می بودیم. ۸ بایت برای nonce و ۸ بایت برای پسورد رمزگذاری شده. با توجه به اینکه ما رمزهای ۸ بایتی رو در جدول می بینیم پس از این شیوه استفاده نشده.
حتی اگر فرض کنیم از عدد دیگه ای مثل userid به عنوان nonce استفاده شده باشه، نباید شاهد رمزهای تکراری در دیتابیس باشیم چرا که احتمال تکرار یک رمز با بلوک های ۶۴ بیتی ۱ در ۲ به توان ۶۴ است (حدود ۲۰ میلیون میلیون میلیون). ما با ۱ میلیون داده طرفیم و این ینی هیچ رمز تکراری در این یک میلیون نباید باشه.
تا اینجا فهمیدیم که ادوب از یک روش برگشت پذیر در رمزگذاری پسوردها استفاده کرده. همچنین از ساده ترین مد که منجر می شه به تکرار نتیجه رمزگذاری در صورت مشابه بودن پسوردها.
بازیابی پسورد
بذارید یه سوال دیگه بپرسیم. پسوردی که رمزگذاری شده اش ۱۱۰edf2294fb8bf4 است و در مجموعه انتخابی ۱.۶ درصد پسوردها رو شامل می شه، چیه؟
بهتره نگاهی به اتفاقات مشابه و آمار هک های دیگه بندازیم و از اون برای تحلیل این داده ها استفاده بکنیم. ۳ سال پیش که Gawker Media هک شد، لیست بیشترین پسوردهای استفاده شده مطابق تصویر زیر بود.
به غیر از کلمه lifehack که یکی از برندهای اون سایت بود، بقیه پسوردهای استفاده شده از کلماتی انتخاب شده که راحت به یاد می مونه و تایپ می شه. با دیدی که از این لیست داریم و نگاهی به ستون یادآوری پسورد می تونیم ۵ پسورد پرکاربرد در داده های لو رفته ادوب رو به دست بیاریم:
دقت کنید که پسوردهای ۸ کاراکتری ۱۲۳۴۵۶۷۸ و password در دو بلوک ذخیره شده اند که نشون میده متن رمز شده حداقل ۹ کاراکتر داشته. به احتمال بسیار زیاد روند این شکلیه که پسورد به اضافه یک بایت صفر(ASCII NUL) می شه که نشون دهنده انتهای رشته در زبان C است و با اضافه شدن ۷ بایت NUL، متن تبدیل به ضریبی از بلوک های ۸ بایتی می شه. بنابراین می تونیم به این نتیجه برسیم که e2a311ba09ab4707 در بلوک دوم، نشون دهنده ۸ بایت صفرِ رمز شده است.
اگر پیش فرض های ما و نتایجی که بهش رسیدیم درست باشه و با توجه به اینکه بلوک e2a311ba09ab4707 در ۲۷ درصد از پسوردهای رمز شده تکرار شده، می تونیم بگیم که ۲۷ درصد پسوردهای کاربران ادوب دقیقا ۸ کاراکتر داره.
می بینید که با کمی تلاش تونستیم ۵ پسورد پرکاربرد ادوب رو به دست بیاریم که پسورد حدود ۲.۷۵ درصد کاربرها بوده و همچنین تونستیم بفهمیم که ۱/۳ پسوردهای کاربران دقیقا ۸ کاراکتر داره. می تونیم تصور کنیم که چه مقدار دیگه اطلاعات می شه از این “بزرگترین جدول کلمات متقاطع تاریخ” به دست آورد.