Проблема
Инструменты enumeration (LinPEAS, Linux Exploit Suggester, pspy) отлично справляются с первой частью задачи: собрать всё, что выглядит нестандартно — SUID-биты на непривычных бинарях, cron-задачи, которые запускаются от root и трогают файлы в записываемых каталогах, записи в sudoers без пароля на нестандартные команды, capabilities на процессах. Проблема в том, что вывод такого сканера — это список гипотез, а не список подтверждённых находок.
Например, SUID-бит на бинарнике из списка GTFOBins формально «уязвим» — но если этот бинарь запускается с ограничивающими флагами, обёрнут в AppArmor-профиль, или путь к нему не входит в PATH обычного пользователя, реальной эскалации может не быть. И наоборот: сканер не всегда видит цепочки — например, когда записываемый через одну уязвимость файл используется совсем другим, непривилегированным на первый взгляд процессом.
Решение
Каждую находку enumeration нужно проводить через простую проверку: «что именно происходит, если я попробую использовать это прямо сейчас, в лабораторных условиях, на копии системы» — и фиксировать результат, а не факт присутствия паттерна.
- SUID/SGID — бинарник действительно даёт вызывающему нужный уровень доступа, или защищён wrapper'ом/ограничением аргументов.
- Cron — задача от root реально пишет/читает по предсказуемому, записываемому пользователем пути, и путь не меняется динамически.
- Sudo — команда в sudoers без пароля реально позволяет выполнить произвольный код (через wildcard, через недостаточно строгий путь, через возможность передать опасные аргументы), а не просто «выглядит широко».
- Capabilities — например,
cap_setuidна непривилегированном бинаре часто мощнее, чем полный SUID root, но проверяется отдельно (getcap -r / 2>/dev/null).
Что проверить руками
- Полный список SUID/SGID файлов вне стандартного набора дистрибутива:
find / -perm -4000 -o -perm -2000 2>/dev/null. - Записываемые пользователем файлы/каталоги, к которым обращаются root-процессы (cron, systemd timers, logrotate).
sudo -lдля текущего пользователя — какие команды разрешены без пароля и с какими аргументами.- Capabilities на бинарях за пределами системного набора.
- Версия ядра и наличие известных local privilege escalation для неё — но с проверкой, а не автоматическим доверием баннеру версии.
Безопасный пример кода
Read-only скрипт сбора признаков для приоритизации ручной проверки — ничего не эксплуатирует, только собирает и группирует находки по категориям, как это делает LinPEAS, но без запуска сторонних бинарей.
#!/usr/bin/env bash
echo "=== SUID/SGID outside common paths ==="
find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null \
| grep -vE "^/usr/(bin|sbin|lib)/(sudo|su|mount|umount|passwd|chsh|chfn|newgrp|gpasswd)$"
echo "=== world-writable files owned by root, referenced by cron ==="
for f in /etc/cron.d/* /etc/crontab; do
[ -f "$f" ] || continue
grep -oE "/[^ ]+" "$f" 2>/dev/null | while read -r path; do
[ -w "$path" ] 2>/dev/null && echo "writable + referenced by cron: $path ($f)"
done
done
echo "=== sudo -l for current user ==="
sudo -l 2>/dev/null
echo "=== non-standard capabilities ==="
getcap -r / 2>/dev/null | grep -v "^/usr/bin/ping\|^/usr/bin/mtr"
Как это должно попасть в отчёт
- Signals: SUID вне стандартного набора, записываемые файлы в цепочке root-процессов, широкие sudo-правила, нестандартные capabilities.
- Controls: минимизация SUID-набора, права 640/750 вместо world-writable, конкретные аргументы вместо wildcard в sudoers, регулярный патч-цикл ядра.
- Retest: тот же скрипт enumeration после исправления не должен находить прежние пути эскалации.