Алгоритм получения LM-хеша при ближайшем рассмотрении выглядит так: пароль, введенный пользователем, превращается в строку фиксированной длины, равной четырнадцати символам. Короткие пароли расширяются добавлением нулевых элементов, а длинные усекаются. Все символы из множества ‘a’-‘z’ переводятся в верхний регистр, и, полученная в результате этой операции, строка расчленяется на две независимые половинки, состоящие из семи символов. Каждая из них играет роль ключа для шифровки последовательности нулей алгоритмом DES. Затем, полученные строки дописываются друг к другу, образуя шестнадцати байтовый LM-хеш.
Алгоритм получения LM-хеша
Независимое хеширование половинок пароля, в 1 000 000 000 000 000 раз уменьшает количество попыток, требующихся для его перебора (а вовсе не в два раза, как это может показаться на первый взгляд). Это же какой талант надо иметь, чтобы допустить такой ляп! Уж сколько раз твердили миру (то бишь разработчикам) - не разводите самодеятельность, используйте проверенные временем алгоритмы, да только все не впрок.
Но эмоции эмоциями, а как все это звучит на языке математики? Путь f - некая хеш функция, а x1…7y8…14 - введенный пользователем пароль. Тогда LM-хеш будет равен f(x)+264*f(y), поскольку область допустимых значений функции f лежит в интервале целых неотрицательных чисел, не превышающих 264, то поиск подходящего пароля заключается в решении двух уравнений (где P - искомый пароль, а H значение LM-хеша):
1. DES(0) - P 1…7® H1…8; [159]
2. DES(0) - P 8…14® H9…16;
Какие существуют способы решения данных уравнений? Алгоритм DES специально разрабатывался так, чтобы, зная исходный (в данном случае строка нулей) и зашифрованный (в данном случае восемь байт хеш - значения) тексты, злоумышленник не мог эффективно вычислить ключ шифрования (искомый пароль). Обсуждение надежности функции DES выходит за рамки данной книги, поэтому все дальнейшие рассуждения исходят из того, что она достаточно криптостойка [160].
Но алгоритм DES нестоек к перебору! Он не требует больших объемов вычислений и допускает существование эффективных реализаций. В среднем случае злоумышленнику потребуется 1+k+k2+k3+k4+k5+k6+k7 операций [161] для подбора пароля, где k максимально допустимое количество символов, использующихся для составления пароля [162]. Это намного меньше ожидаемого количества операций, необходимых для подбора четырнадцати символьного пароля!
1+k+k2+k3+k4+k5+k6+k7 «(1+k+k2+k3+k4+k5+k6+k7++k8+k9+k10+k11+k12+k13+k14)*1/2, где знак “«” обозначает «намного меньше». И пароль, состоящий из восьми и более символов, окажется ничуть не сложнее пароля, состоящего всего из семи символов! Фактически система запрашивает два семисимвольных пароля и обрабатывает их независимо друг от друга [163].
Причем, пароли, состоящие менее чем из восьми символов, легко распознать! Если пароль, введенный пользователем, оказывается меньше четырнадцати символов, то система расширяет его до требуемой длины нулями. Пусть пользователь ввел пароль из семи или менее символов, тогда P8…14 = 0, а DES(0) - P 8…14® 0xAAD3B435B5140EE - однако, константа! (А, разработчики, однако, чукчи).
Поэтому, если старшие восемь байт LM-хеша равны 0xAAD3B435B5140EE, то исходный пароль состоит из семи или менее символов. Впрочем, на результаты поиска это не оказывает сильного влияния (дальше будет объяснено почему).
Если оптимизировать алгоритм, то скорость перебора можно увеличить вдвое! В самом деле, совершенно ни к чему дважды вычислять значение функции DES в уравнении 1 и в уравнении 2, поскольку области определения обеих функций одинаковы. Следовательно, для каждого P достаточно один раз вычислить значение DES(0) и поочередно сравнить его с H1…8; и с H9…16. Если пренебречь временем, затраченным на сравнение значения функции с H1…8 и H9…16 (а их для ускорения можно поместить в один 16-разрядный регистр), то скорость перебора возрастет вдвое!
Однако хеш никогда не передается в открытом виде по сети, поэтому злоумышленнику перехватить его невозможно. Клиент передает серверу challenge, зашифрованный хеш - значением пароля, с помощью алгоритма DES. Поскольку, сомневаться в надежности алгоритма DES не приходится, то, кажется, что вычислить хеш пароля никакой возможности нет, и остается действовать только методом перебора.
Поскольку хеш представляет собой 16-байтовую строку, то всего возможно 2128 комбинаций, то есть перебор потребует нереальных вычислительных мощностей, недоступных злоумышленнику. Даже для современных суперкомпьютеров эта задача слишком сложна. Если, конечно, реализация алгоритма DES свободна от ошибок [164].
А такие ошибки и в самом деле есть - функция DES трижды шифрует challenge, используя в качестве ключей различные фрагменты хеш - значения пароля, чем значительно уменьшает количество попыток, требуемых для его подбора. Алгоритм шифрования при близком рассмотрении выглядит так:
К шестнадцатибайтовому хеш - значению дописываются пять нулей, образуя последовательность из двадцати одного байта (16+5=21) обозначенную в этой книге как h1…21.
Эта последовательность разрезается на три равных части по семь байт, обозначенные h1…7, h8…14, h15…21.
Каждая их них используется в качестве ключа для шифровки challenge, переданного сервером, с помощью алгоритма DES.
Полученный результат (обозначенный как R) отсылается на сервер. Весь процесс математически можно выразить так:
1. DES(challenge) - h 1…7® R1…8
2. DES(challenge) - h 8…14® R9…16
3. DES(challenge) - h 15…21® R17…24
Создается такое впечатление, что парни из Microsoft не могут шифровать строки, состоящие более чем из семи символов, вот поэтому-то и прибегают к их разрезанию.
Поскольку пять старших байт ключа h15…21 известны заранее (они содержат нули, дописанные для расширения ключа до двадцатиоднобайтовой строки), то для решения уравнения DES(challenge) - h 15…21® R17…24 необходимо перебрать всего два байта. В худшем случае это потребует 216 операций, а в среднем вдвое меньше 215. Если же длина пароля составляет менее восьми символов, то h15…h21 всегда равны 0x04EE0000000000, поэтому короткие пароли элементарно распознать с одного взгляда!
В свою очередь, это облегчает решение уравнения DES(0) - P 8…14®H9…16, поскольку H15…16=h15…16. Перебором всех возможных значений P8…14, всего за 1+k+k2+k3+k4+k5+k6+k7 операций можно найти всех «кандидатов» в пароли, которых будет не более чем (1+k+k2+k3+k4+k5+k6+k7)/216.
Остается перебрать 28*(1+k+k2+k3+k4+k5+k6+k7)/216 комбинаций, чтобы среди «кандидатов» в ключи уравнения DES(challenge) - h 8…14® R9…16 найти единственный действительный ключ.