Існує поширене помилкове уявлення про те, що хеш і шифрування – це одне і те ж. Вони не є. Хеш є незворотним. Візьмемо наступний приклад:
$ echo -n Password123 | md5sum
42f749ade7f9e195bf475f37a44cafcb -
Передаємо рядок "Password123" алгоритму MD5 (algo), який виконує математичні операції та повертає згенерований хеш шістнадцяткового кодування. Єдиний спосіб отримати однакове вихідне значення хеша - ввести оригінальний вхід algo. Є конфлікти, але ми можемо поговорити про це пізніше.
Більшість алгоритмів хешування виводять шістнадцятково закодований двійковий рядок фіксованої довжини. Інші, як у цьому прикладі, використовують рядки, закодовані в base64, як вихідні дані. Зверніть увагу, що довжина завжди однакова:
{SHA} uNF8eZRJ8jmr8WTjyocRJPVpe7w=
{SHA}lqdu/Zr6o2dgIER8Up1/7lcUtgw=
{SHA}qYUOwLMlDEuukA5HCT4LR1kQzco=
{SHA}MXZBCpyWJ7TTs1w2kgGJslwNwTg=
{SHA}2sAPLaUh9Mz0bI+XxKEg7qyABe8=
TL; Dr.
Я не хочу багато говорити про шифрування (бо ті речі для книг), але важливо вміти відрізняти хеш-рядки від зашифрованих рядків. Шифрування зазвичай заповнює рядок, який задовольняє певну довжину до того, як відбудеться шифрування. Для розшифрування також потрібен ключ (або пароль). Якщо використовується зашифрований пароль, string змінюватиметься залежно від довжини введення. Якщо ви бачите купу зашифрованих паролів різної довжини, можливо, ви маєте справу з шифруванням, а не з хешуванням. AES-256-CBC Приклад Зашифрований рядок і пов'язаний звичайний текст (з ключем "ASDF"):
foobar | U2FsdGVkX19G+KtytNHdj6yH2AVvX26pEmtunS/PRnU= foobarfoobar | U2FsdGVkX18sPpIvN6nVh68lOUCcb3gR2fKbCCnBxog= foobarfoobarfoobar | U2FsdGVkX1/EOnUt57TCW4Rh0EdNnWX+lDatuQv2xEXXeAeowW0XG/EXJUe9aSUz $ cat шифровані_паролі U2FsdGVkX19G+KtytNHdj6yH2AVvX26pEmtunS/PRnU= U2FsdGVkX18sPpIvN6nVh68lOUCcb3gR2fKbCCnBxog= U2FsdGVkX1/EOnUt57TCW4Rh0EdNnWX lDatuQv2xEXXeAeowW0XG/EXJUe9aSUz $ for i in `cat encrypted_passwords`; do echo $i | openssl enc -base64 -d -aes-256-cbc -pass pass:asdf; відлуння; Готово Фубар foobarfoobar foobarfoobarfoobar
Тепер ви можете подумати: напевно, ви маєте рацію. Однак ключовий матеріал повинен бути доступним для системи. Це означає, що, по суті, простий текстовий головний пароль знаходиться десь - чи то як ключ RSA, чи пароль. Або пароль у файлі, вбудований у базу даних, жорстко закодований у програмі або десь у пам'яті. pfft, ніхто'не буде використовувати asdf як ключ для шифрування своїх користувачів' паролів
Використовуйте той самий рядок для MD5:
foobar | 3858f62230ac3c915f300c664312c63f foobarfoobar | 59faa421729e846dd800dce59943bfc0 foobarfoobarfoobar | 1352aadab322d1a033c27964be0965db
Хеш-пароль далеко не ідеальний, насправді він трохи поганий, але він гірший за шифрування через те, що він намагається досягти. Користувачі вибирають абсолютний мінімум частіше, ніж не, а також можуть використовувати його на декількох сайтах. Багато «хаків» насправді є не що інше, як атаки на повторне використання облікових даних. Якщо початковим компромісом було використання шифрування, то єдине зусилля, яке зловмисник повинен докласти, це знайти ключ, який розшифрує всі паролі. Для хешування їм потрібно принаймні докласти зусиль, щоб їх зламати. При використанні з сучасними алгоритмами, такими як sha512crypt, bcrypt, scrypt або argon2, хеш може вимагати значних зусиль для злому.
salt - це додавання рядка до пароля перед хешуванням. Сіль для кожного хеша має бути унікальною, зазвичай вибраною випадковим чином, оскільки суть полягає в тому, щоб одне й те саме значення хеша «пароля» відкритого тексту щоразу було різним. Це ускладнює життя зломників паролів, оскільки для того, щоб перевірити слово «пароль» кожного з 1000 користувачів, кожен з яких має унікальний SALT, вони повинні робити роботу 1000 разів - один раз на користувача/SALT. Це також означає, що вони не можуть ефективно використовувати попередньо скомпільовані словники або таблиці rainbow (зазвичай...), оскільки їм потрібна спеціальна кількість солі.
Сайти іноді це псують і використовують універсальну сіль для всіх користувачів; Це суперечить цілі.
Нижче наведено хеш SHA1 із засоленням:
b353977827f67a4ae0318f3a9447fae1c13d9d90:b8d18ca |___________________________________________| хэш | соль | separator
Відкритий текст цього хеша — «пароль». Його значення солі "b8d18ca" і використовує API SHA1 ($salt.$pass). Це означає, що алгоритм отримує відкритий текст пароля, генерує сіль і додає його перед відкритим текстом. Коли веб-сайт або програма намагатиметься підтвердити ваш пароль, у майбутньому він візьме ваш пароль у відкритому тексті як вхідні дані, зчитує значення солі в збереженому хеші, додає його перед вибраним вами паролем і порівнює згенероване хеш-значення зі збереженим хеш-значенням. Крекінг Якщо ви не знаєте, що його частина є сіллю, хеш створить такий звичайний текст:
b8d18capassword
Оскільки алгоритм вводить звичайний текст, сіль і згенерований хеш-значення можуть залишатися прозорими для користувача. Під час крекінгу, якщо алгоритм є солоним, нам потрібно знати соль, щоб ми могли надати її під час генерації відкритого тексту-кандидата.
При правильному виконанні засолення може зробити крекінг більш трудомістким. Використовуючи Random salt, ви змушуєте Cracker витрачати час, намагаючись зламати невідповідні хеш-значення salt. Це приблизно виконує зусилля, необхідні для швидкості_пристрою / кількості_солей, оскільки нам потрібно створити кандидата для кожної солі. Якщо сіль статична, то математичні операції однакові... швидкість_пристрою / 1. Інший спосіб перегляду Це:
наші GTX 980 тріщини SHA1($salt.$pass) at 3576.8 MH/s або 3.5 мільярдів кандидатів за секунду Наш хешлист містить 1000 унікальних солей 3 500 000 000 / 1000 = 3 500 000 candidates per second
Це на три порядки повільніше, втрачаючи 99,9%. При використанні статичної солі це виглядає так:
Our GTX 980 cracks SHA1($salt.$pass) at 3576,8 MH/s або 3,5 мільярда кандидатів за секунду Наш хешлист містить 1 унікальний соль 3 500 000 000 / 1 = 3 500 000 000 candidates per second
Якщо це не має сенсу, продовжуйте читати, у нас буде гарна діаграма пізніше...
Іншим поширеним покращенням порівняно з простим «хешуванням цього звичайного тексту» є те, що «хешуйте цей звичайний текст, потім хешуйте цей результат, а потім хешуйте цей результат» повторюється тисячі разів. Це дозволяє злому пароля виконувати тисячі разів під час спроби одного пароля-кандидата. Це називається ітерацією, циклом або змінною вартістю. Деякі алгоритми хешування паролів використовують жорстко закодовані раунди ітерації; Інші Git. зробити його настроюваним у частині самого хеша. Наприклад, md5crypt() використовує MD5, включаючи salt, і робить рівно 1000 циклів. sha512crypt() використовує sha512, включаючи соль, і цикл налаштовуваної кількості разів (за замовчуванням 5000).
Ітерація в основному впливає на вартість обчислювального циклу алгоритму хешування, а не на використання його пам'яті чи інші фактори. Це також важливі атаки, коли дизайн оптимізований для протистояння певним типам хеш-типів, але це занадто бур'ян, щоб обговорювати його тут.
Давайте розглянемо кілька прикладів, щоб продемонструвати вплив вибору алгоритму хешування, будь то солоний, використання кількох ітерацій тощо. Припустимо, зловмисник зібрав хеш 1000 користувачів з якогось зараженого веб-сайту, які хочуть виконати лише одну просту атаку, перевіряючи кожен пароль.Хеш - 143 мільйони паролів-кандидатів.
Тип хеша, який використовує заражений веб-сайт, матиме величезний вплив на час, необхідний для атаки зловмисника. Це графік того, скільки (відносно, приблизно) потрібно секунд, щоб завершити цю атаку, залежно від типу хеша, який використовується, де Стандартна відеокарта:
Ну, це марно! Найсильніші типи хешування набагато повільніші, але швидші. Тип просто сплющений, поки нічого не буде. Давайте знову спробуємо той самий масштаб даних, використовуючи логарифмічний час осі X. Коли смуги переміщуються зліва направо, вони збільшуються на 10 у ступені:
Отже, деякі важливі моменти: коли ви хочете зламати деякі хеші пароля, один раунд простіше, ніж кілька раундів і без солі, ніж додавання солі. Навпаки, коли певна компанія або веб-сайт оголошує про витік даних, що містить дані користувача, а) бажано, щоб пароль був хеширований, а не просто звичайний текст; б) вони краще підсолені, а не просто хешовані; c) Краще, щоб вони завжди використовували потужний кількораундовий солоний хеш, а не просто один раунд.
Перш ніж спробувати зламати даний хеш пароля, зломщику належить з'ясувати, який алгоритм хешування використовується для його реалізації. Ідентифікація типів хешування зазвичай проста, але не завжди. Крекери часто роблять обґрунтовані здогадки на основі підказок, таких як довжина хеша та формат. Зрештою, єдиний спосіб переконатися, що вгадування типу хеша є правильним, це якщо хеш зламаний.
Тут і тут наведено кілька чудових ресурсів для цього завдання, і всі вони показують, як виглядають загальні хеш-значення.
У Kali Linux доступний пакет "hash-identifier" (доступний тут), який допомагає ідентифікувати невідомі типи хешів.
Зіткнення виникає, коли два різних входи призводять до однакового хеш-виходу. Це погано (очевидно). Що стосується паролів, це може означати, що я, можливо, не зламав ваш фактичний пароль, але оскільки я знайшов вхід, який генерує таке ж хеш-значення, я можу використати звичайне текстове значення, щоб обдурити систему, щоб вона думала, що пароль є законним.
Microsoft Office використовує алгоритм, схильний до конфліктів протягом багатьох років у своєму захисті документів. Не рідкість виявляти кілька конфліктів для одного хеша, і всі ці конфлікти розблокують документ.
Як тільки виявлено конфлікт, алгоритм фактично руйнується. Якщо це трапилося один раз, то статистично, швидше за все, це повториться. Єдине, що заважає нам, це час і потужність обробки. У міру того, як алгоритми стають більш надійними, для створення алгоритмів-кандидатів і порівняння хеш-результатів для їх пошуку потрібні більше потужностей і часу. Тому дизайнери все більше вміють створювати алгоритми, які менш схильні до конфліктів.