Паролі sql-сервера керівництво по злому

SQL сервер використовує недокументовану функцію pwdencrypt () для створення хешів призначених для користувача паролів, які потім зберігаються в головній базі. Іншими словами
- паролі крипти і зберігаються в зашифрованому вигляді.
Отримати їх можна простим запитом, так як
вони зберігаються в звичайній базі даних:

select password from master.dbo.sysxlogins where
name = 'sa'

Хеш пароля виглядає приблизно так:

Виглядає це треба сказати страшно ... Давай-но розберемося, що впливає на його формування:

Спробуємо наприклад закріптовать пароль 'foo'.
Робиться це командою:

Ну а якщо спробуємо через пару секунд ще раз, то отримаємо:

Легко помітити, що ми отримуємо різні хеш-кодування, що означає, що хеш залежить від часу. Таким чином два або більш користувачів можуть мати мати однакові паролі, але при цьому хеші паролів будуть різні.

Тепер давай спробуємо зашифрувати 'AAAAAA':

Якщо уважніше придивитися до отриманий хеш, то його можна умовно розділити на чотири частини:

0x0100
84449305
43174C59CC918D34B6A12C9CC9EF99C4769F819B
43174C59CC918D34B6A12C9CC9EF99C4769F819B

Причому третя і четверта частини у нас абсолютно тотожні. Це пов'язано з тим, що з незрозумілих причин пароль зберігається двічі: в перший раз «як є» (тобто з урахуванням регістру), а другий раз - у верхньому регістрі. Так як в нашому прикладі вихідний пароль весь складався з букв у верхньому регістрі, то в результаті «подвійного запису», ми отримали абсолютно ідентичні частини хешу.
Гіпотетично це значно скорочує
час брутфорса, так як треба перебирати
тільки літери верхнього регістру.

Але чи впливає час на хеш безпосередньо? Відповідь - ні. Функція Time () створює лише вихідну точку для функції srand (), яка генерує два випадкових числа. Ці числа об'єднуються (з великою часткою ймовірності можна також припустити, що ці числа також приводяться до «скороченим варіантом») і виходить salt, який в подальшому використовується при «виробництві» хешу.

Пароль перетворюється в Unicode і до нього додається salt. Потім все це проходить через функції криптування в advapi32.dll - в результаті ми отримує «третю» частина хешу (як ми розглядали в пункті про вплив регістра).
Потім пароль перетворюється в верхній регістр і зазначені маніпуляції повторюються - отримуємо «четверту» частина хешу.
Потім проводиться «збірка» остаточного варіант хешу, який і буде зберігається в базі:

Береться незмінний заголовок:

Потім той salt, який використовувався при криптуванням пароля:

Третя і четверта частини - безпосередньо сам пароль (в незмінному вигляді і в верхньому регістрі відповідно):

Усе! Виходить той самий, негарний і страшний хеш:


Як відбувається ідентифікація

Користувач вводить пару логін / пароль.
Спочатку відбувається перевірка на наявність користувача з даним логіном. Якщо перевірка успішна і користувач існує, то з відповідного хешу витягується salt (друга частина хешу) і введений користувачем пароль крипти з використанням цього salt. Потім отриманий результат порівнюється з наявним хешем в базі. У разі збігу користувач отримує доступ, в іншому - йде згадувати пароль ...

Не зовсім зрозуміло, чому пароль зберігається в хеше двічі - адже маючи хешировать пароль у верхньому регістрі, атакуючий має можливість істотно скоротити обсяг роботи: на початку «розколоти» пароль у верхньому регістрі і дізнатися які символи використовуються, а потім просто провести перевірку всіх комбінацій цих символів у верхньому і нижньому регістрах. Таким чином обсяг роботи по даному алгоритму в десятки, сотні і навіть тисячі разів (залежить від довжини пароля) менше, ніж при спробі зламати чутливий до регістру пароль як то кажуть в «лоб».

Для практичної реалізації цієї ідеї була написана консольна програма, лістинг якої я тобі і пропоную
(Дуже корисно було б розібрати лістинг і
зрозуміти як діє програма - втім
це, як правило, на твій розсуд):

Існує також неконсольная версія даного крякери. Її творці стверджують, що вона працює швидше ... але вона платна, а ти ж платити не любиш ...

Покажи цю статтю друзям: