
Мониторинг процессов Linux без прав root
pspy — это инструмент командной строки, предназначенный для слежки за процессами без необходимости прав root. Он позволяет видеть команды, запускаемые другими пользователями, cron-задания и т.п. по мере их выполнения. Отлично подходит для перечисления систем Linux в CTF. Также отлично демонстрирует коллегам, почему передавать секреты в качестве аргументов командной строки — плохая идея.
Инструмент собирает информацию из сканирования procfs. Наблюдатели inotify, размещённые на выбранных частях файловой системы, запускают эти сканирования, чтобы ловить короткоживущие процессы.
Загрузите инструмент на машину Linux, которую хотите проверить. Сначала получите бинарные файлы. Скачайте опубликованные бинарники здесь:
pspy32 скачатьpspy64 скачатьpspy32s скачатьpspy64s скачатьСтатически скомпилированные файлы должны работать в любой системе Linux, но они довольно большие (~4 МБ). Если размер имеет значение, попробуйте маленькие версии, которые зависят от libc и сжаты с помощью UPX (~1 МБ).
Либо используйте Go, установленный в вашей системе, либо запустите процесс сборки на основе Docker, который использовался для создания релиза.
Для последнего убедитесь, что Docker установлен, затем выполните make build-build-image для сборки Docker-образа, после чего make build для сборки бинарников с его помощью.
Вы можете запустить pspy --help, чтобы узнать о флагах и их значении.
Краткое описание выглядит так:
Настройки по умолчанию подходят для большинства применений.
Наблюдение за файлами внутри /usr наиболее важно, так как многие инструменты обращаются к библиотекам внутри него.
Некоторые более сложные примеры:
# печатать и команды, и события файловой системы, сканировать procfs каждые 1000 мс (=1 сек)
./pspy64 -pf -i 1000
# разместить наблюдатели рекурсивно в двух каталогах и нерекурсивно в третьем
./pspy64 -r /path/to/first/recursive/dir -r /path/to/second/recursive/dir -d /path/to/the/non-recursive/dir
# отключить вывод обнаруженных команд, но включить события файловой системы
./pspy64 -p=false -f
Чтобы увидеть инструмент в действии, просто склонируйте репозиторий и выполните make example (требуется Docker).
Известно, что передавать пароли в качестве аргументов командной строки небезопасно, и этот пример можно использовать для демонстрации этого.
Команда запускает контейнер Debian, в котором секретное cron-задание, выполняемое от root, меняет пароль пользователя каждую минуту.
pspy запускается на переднем плане от пользователя myuser и сканирует процессы.
Вы должны увидеть вывод, похожий на этот:
~/pspy (master) $ make example
[...]
docker run -it --rm local/pspy-example:latest
[+] cron started
[+] Running as user uid=1000(myuser) gid=1000(myuser) groups=1000(myuser),27(sudo)
[+] Starting pspy now...
Watching recursively : [/usr /tmp /etc /home /var /opt] (6)
Watching non-recursively: [] (0)
Printing: processes=true file-system events=false
2018/02/18 21:00:03 Inotify watcher limit: 524288 (/proc/sys/fs/inotify/max_user_watches)
2018/02/18 21:00:03 Inotify watchers set up: Watching 1030 directories - watching now
2018/02/18 21:00:03 CMD: UID=0 PID=9 | cron -f
2018/02/18 21:00:03 CMD: UID=0 PID=7 | sudo cron -f
2018/02/18 21:00:03 CMD: UID=1000 PID=14 | pspy
2018/02/18 21:00:03 CMD: UID=1000 PID=1 | /bin/bash /entrypoint.sh
2018/02/18 21:01:01 CMD: UID=0 PID=20 | CRON -f
2018/02/18 21:01:01 CMD: UID=0 PID=21 | CRON -f
2018/02/18 21:01:01 CMD: UID=0 PID=22 | python3 /root/scripts/password_reset.py
2018/02/18 21:01:01 CMD: UID=0 PID=25 |
2018/02/18 21:01:01 CMD: UID=??? PID=24 | ???
2018/02/18 21:01:01 CMD: UID=0 PID=23 | /bin/sh -c /bin/echo -e "KI5PZQ2ZPWQXJKEL\nKI5PZQ2ZPWQXJKEL" | passwd myuser
2018/02/18 21:01:01 CMD: UID=0 PID=26 | /usr/sbin/sendmail -i -FCronDaemon -B8BITMIME -oem root
2018/02/18 21:01:01 CMD: UID=101 PID=27 |
2018/02/18 21:01:01 CMD: UID=8 PID=28 | /usr/sbin/exim4 -Mc 1enW4z-00000Q-Mk
Сначала pspy выводит все запущенные в данный момент процессы, каждый с PID, UID и командной строкой.
Когда pspy обнаруживает новый процесс, он добавляет строку в этот журнал.
В этом примере вы видите процесс с PID 23, который, похоже, меняет пароль пользователя myuser.
Это результат работы Python-скрипта, используемого в личном crontab root /var/spool/cron/crontabs/root, который выполняет эту команду оболочки (проверьте crontab и скрипт).
Обратите внимание, что myuser не может видеть ни crontab, ни Python-скрипт.
С pspy он, тем не менее, может видеть команды.
Ниже приведён пример с машины Shrek с Hack The Box. В этом CTF-задании требуется эксплуатировать скрытое cron-задание, которое меняет владельца всех файлов в папке. Уязвимость заключается в небезопасном использовании wildcard вместе с chmod (подробности для заинтересованного читателя). Для её поиска и эксплуатации требуется немало догадок. Однако с pspy cron-задание легко найти и проанализировать:

Существуют инструменты для вывода всех процессов, выполняемых в Linux, включая завершённые. Например, forkstat. Он получает уведомления от ядра о событиях, связанных с процессами, таких как fork и exec.
Эти инструменты требуют прав root, но это не должно создавать ложного чувства безопасности.
Ничто не мешает вам следить за процессами, запущенными в системе Linux.
Много информации видно в procfs, пока процесс работает.
Единственная проблема — нужно поймать короткоживущие процессы в очень короткий промежуток времени, пока они живы.
Сканирование каталога /proc на предмет новых PID в бесконечном цикле решает задачу, но потребляет много CPU.
Более скрытный способ — использовать следующий трюк.
Процессы обычно обращаются к файлам, таким как библиотеки в /usr, временные файлы в /tmp, файлы журналов в /var, ...
Используя API inotify, вы можете получать уведомления, когда эти файлы создаются, изменяются, удаляются, запрашиваются и т.д.
Linux не требует привилегированного пользователя для этого API, так как он необходим для многих безобидных приложений (например, текстовые редакторы показывают обновлённый проводник файлов).
Таким образом, хотя обычные пользователи не могут напрямую отслеживать процессы, они могут отслеживать воздействие процессов на файловую систему.
Мы можем использовать события файловой системы как триггер для сканирования /proc, надеясь, что сможем сделать это достаточно быстро, чтобы поймать процессы.
Именно это и делает pspy.
Нет гарантии, что вы не пропустите какой-либо процесс, но, по моим экспериментам, шансы хорошие.
В целом, чем дольше процессы выполняются, тем больше шансов их поймать.
Логотип: "By Creative Tail [CC BY 4.0 (http://creativecommons.org/licenses/by/4.0)], via Wikimedia Commons" (ссылка)