MAATRIX / Блог / Как проверить подрядчика на безопасность до того, как дадите ему root

Как проверить подрядчика на безопасность до того, как дадите ему root

MAATRIX

Момент, когда вы отправляете подрядчику пароль root или добавляете его ключ в authorized_keys, длится секунд десять — скопировать, вставить, отправить. Но именно в эту секунду решается, сможет ли человек, которого вы, скорее всего, никогда не видели лично, читать всё на сервере, менять всё и заметать следы всех своих действий. Это не вопрос доверия к конкретному человеку — доверие тут не главный параметр. Это вопрос того, понимаете ли вы, что именно даёте, и сделали ли несколько дешёвых вещей заранее, которые эту секунду делают менее рискованной.

Root — это не "доступ побольше", это доступ без границ

Разница между ограниченным доступом и root не количественная, а качественная. Пользователь с правами на конкретную директорию физически не может выйти за её пределы — файловая система не позволит, будь у него хоть сколько злого умысла. У root такой границы нет нигде: он читает файлы любого пользователя, включая приватные ключи, .env с секретами, дампы баз с чужими персональными данными; он может выключить сам механизм разграничения прав, потому что тот тоже подчиняется root; он видит содержимое оперативной памяти других процессов — а значит потенциально расшифрованные данные, которые на диске лежат зашифрованными.

Отсюда практический вывод, который легко упустить в спешке: вопрос "что именно нужно подрядчику для задачи" и вопрос "что подрядчик сможет сделать с root" — два разных вопроса с разными ответами. Первый может звучать скромно: "поправить конфиг nginx". Второй всегда один и тот же независимо от формулировки задачи: "всё, что вообще есть на сервере" — учётки других сервисов на том же хосте, чужие проекты на том же VPS, ключи во внешние системы из переменных окружения. Всё это физически достижимо, даже если требовалось только одно.

Это не значит, что root нельзя выдавать никогда — иногда задача реально требует полного административного контроля (миграция ОС, перенастройка ядра, работа с драйверами). Значит это другое: решение выдать root стоит принимать осознанно, зная полную стоимость, а не потому, что разбираться с ограничениями лень или некогда.

Root умеет заметать собственные следы

Второе, о чём редко думают до выдачи доступа: root умеет не только действовать без ограничений, но и скрывать, что именно делал. Это важно, потому что интуитивно кажется — "если что-то пойдёт не так, потом посмотрю в логах". С root это предположение часто ложное.

Несколько конкретных механизмов, которыми пользуется — не обязательно злонамеренно, иногда просто по привычке чистить за собой — любой, у кого есть root:

# Очистить историю команд текущей сессии, дальше её не писать вовсе
history -c && history -w
unset HISTFILE
# Затереть системные логи входов и авторизации
> /var/log/auth.log
> /var/log/secure          # RHEL/CentOS-семейство
# Временно выключить аудит, сделать своё, включить обратно
auditctl -e 0 && ...действия... && auditctl -e 1
# Подделать время модификации файла, чтобы не бросался в глаза
touch -d "2026-01-15 10:00:00" /etc/cron.d/system-check

Дело не в том, что каждый подрядчик обязательно это сделает — большинство никогда так не поступит. Дело в том, что без заранее настроенных мер у вас физически нет способа отличить "подрядчик ничего лишнего не делал" от "подрядчик всё почистил за собой": оба случая выглядят одинаково — чистые логи и пустая история. Журнал, который можно посмотреть только на том же сервере, под тем же root, — это журнал, который root же и может отредактировать. Полезным он становится только тогда, когда копия уходит туда, куда root доступа не имеет — об этом в разделе про логирование ниже.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Root умеет оставлять себе доступ на будущее

Третий и, пожалуй, наименее очевидный риск — root может создать себе точку возврата, которая переживёт формальное окончание контракта, смену пароля и даже удаление выданного аккаунта. Разница с обычным "забыли отозвать ключ" в том, что забытый ключ виден при простой проверке authorized_keys выданного аккаунта, а спрятанная точка доступа сознательно размещена там, где её не станут искать. Несколько реалистичных вариантов:

Собственный ключ в чужом или системном authorized_keys. Ключ подрядчика в файле его выданного аккаунта — ожидаемо и заметно. Но ничто не мешает добавить второй ключ в authorized_keys пользователя root, deploy-аккаунта или любого другого системного пользователя — этот файл никто не проверяет, если проверка ограничивается только тем аккаунтом, который выдавали изначально.

Пользователь с UID 0, не являющийся root по имени. В Linux уникальность имени не означает уникальность идентификатора — можно создать второго "root" под другим именем:

useradd -o -u 0 -g 0 -m sysmonitor

Флаг -o разрешает не-уникальный UID. В /etc/passwd появится строка вида sysmonitor:x:0:0::/home/sysmonitor:/bin/bash — по имени безобидный технический аккаунт, а по правам полноценный root со своим SSH-ключом, независимым от учётки, которую отзовут по завершении работы.

Cron-задача или systemd-таймер под системный. Скрипт, который раз в сутки проверяет, не отозвали ли доступ, и если да — тихо его восстанавливает:

# /etc/cron.d/system-health — выглядит как легитимная проверка
*/30 * * * * root /usr/local/bin/.health-check.sh >/dev/null 2>&1

Setuid-бинарник, дающий root без пароля и без ключа вообще. Копия shell с установленным битом setuid работает как чёрный ход, не завязанный ни на какую учётную запись:

cp /bin/bash /usr/local/sbin/.sysupdate
chmod u+s /usr/local/sbin/.sysupdate

Любой, кто запустит этот файл, получит shell с правами root — доступ, который переживёт не только отзыв SSH-ключа, но и полную смену паролей всех аккаунтов.

Ни один из этих приёмов не требует продвинутых навыков — это базовые, хорошо задокументированные техники. От них нельзя защититься "доверием к квалификации" — наоборот, чем опытнее человек, тем очевиднее для него эти возможности. Защита — сделать так, чтобы после работы это было легко проверить (раздел про аудит ниже), и заранее сузить сам объём того, что доступно под именем root — той же логике для постоянной команды посвящена статья как раздать доступ без выдачи root.

Прежде чем выдавать: точно ли нужен именно root

Первая и самая дешёвая мера снижения риска — не техническая настройка, а один вопрос себе до отправки пароля: какая конкретно команда требует полных прав. На практике абсолютное большинство задач, ради которых по привычке выдают root, этого не требуют.

ЗадачаКажется, нужен rootНа самом деле достаточно
Перезапустить сервисДаsudo только на systemctl restart myapp
Посмотреть логи приложенияДаЧтение конкретной директории или sudo на journalctl -u myapp
Обновить код, передеплоитьДаПрава на директорию проекта плюс sudo на команду деплоя
Настроить бэкап одного сервисаДаДоступ к директории с данными и к cron конкретного пользователя
Обновить ядро, перенастроить сетьДаЗдесь root правда может понадобиться — случай, когда полные права оправданы

Если задача укладывается в первые четыре строки — а на практике так происходит чаще, чем кажется, — точечный sudo закрывает потребность полностью:

# /etc/sudoers.d/contractor_migration
contractor_ivan ALL=(root) NOPASSWD: /usr/bin/systemctl restart myapp.service, \
  /usr/bin/systemctl status myapp.service, \
  /usr/bin/journalctl -u myapp.service *

Честная оговорка: точечный sudo — существенное снижение риска, а не гарантия. Слишком широкие маски вроде /usr/bin/systemctl * или разрешение запускать скрипт, который сам вызывает произвольные команды, могут стать путём эскалации до полного root.

Если после честного разбора выясняется, что root всё-таки нужен — не потому что "так проще", а потому что задача реально требует уровня системы в целом — переходите к следующим двум мерам, которые риск не устраняют, но заметно снижают.

Временные, а не постоянные учётные данные

Второй по дешевизне и эффективности шаг — доступ, который истекает сам, без необходимости кому-то об этом вспомнить. Постоянный доступ остаётся действительным, пока кто-то не отзовёт его отдельным действием; временный по умолчанию перестаёт работать, и действие нужно, только если его требуется продлить. На уровне Linux это одна команда при создании аккаунта:

useradd -m -e 2026-09-20 contractor_ivan

Флаг -e жёстко ограничивает дату — после неё учётная запись блокируется автоматически на уровне системы, независимо от того, помнит кто-то про неё или нет. Проверить и при необходимости продлить:

chage -l contractor_ivan
chage -E 2026-10-05 contractor_ivan

Если в инфраструктуре уже настроен свой SSH CA, ещё надёжнее — сертификат с коротким сроком жизни вместо статического ключа, который сам перестаёт проходить проверку по истечении срока и не требует отдельного удаления из authorized_keys:

ssh-keygen -s ca_key -I contractor_ivan -n contractor_ivan -V +5d contractor_ivan_key.pub

Флаг -V +5d — сертификат действует пять дней от выпуска. У облачных провайдеров та же логика на уровне IAM: где поддерживаются временные ключи или роли с ограниченным сроком вместо постоянных ключей API — используйте их для подрядчика по умолчанию.

Честная оговорка: истечение срока учётки не отменяет уже созданные скрытые точки доступа из предыдущего раздела — второй UID 0, cron-бэкдор или setuid-бинарник продолжат работать и после блокировки аккаунта, потому что формально с ним не связаны. Временные credentials закрывают один канал, а не гарантируют отсутствие остальных.

Логирование, включённое до выдачи доступа, а не после инцидента

Третья мера дешёвая по исполнению и почти всегда недооценённая: базовое логирование действий подрядчика, включённое заранее, до того как он впервые зашёл на сервер. Смысл не в том, чтобы поймать что-то в реальном времени — почти никто не читает логи live — а в том, чтобы после факта было что просмотреть, если что-то сломается.

Минимальный вариант — включить аудит системных вызовов через auditd и настроить отдельный лог для sudo-команд:

# Логировать все запуски процессов с меткой для конкретного подрядчика
auditctl -a exit,always -F arch=b64 -S execve -k contractor_actions
ausearch -k contractor_actions
# /etc/sudoers.d/contractor_ivan — логировать ввод и вывод каждой sudo-команды
Defaults:contractor_ivan logfile="/var/log/sudo-contractor_ivan.log"
Defaults:contractor_ivan log_input, log_output

Ключевой нюанс, из-за которого это стоит делать заранее, а не потом: логи, которые лежат только локально на том же сервере, куда у подрядчика root, — это логи, которые он же может почистить (см. раздел про заметание следов выше). Ценность появляется, только когда копия немедленно уходит туда, куда доступа у него нет — на отдельный лог-сервер или в облачный сервис логирования:

# /etc/rsyslog.d/50-remote.conf — переслать логи на отдельный сервер сразу же
*.* @@log-collector.internal:514

С такой пересылкой, даже если подрядчик подчистит локальные логи, копия, ушедшая раньше, уже недоступна ему для редактирования. Для задач с повышенной чувствительностью — продовые данные, финансы, персональные данные клиентов — стоит записывать не только команды, но и весь терминальный вывод сессии через bastion-хост или инструменты записи сессий; принцип тот же — запись должна уходить туда, где root подрядчика её не достаёт.

Обязательный аудит после завершения работы

Последний и, возможно, самый часто пропускаемый шаг — то, что должно происходить сразу после формального завершения работы, до закрытия контракта. Логика простая: если у человека был root, у него была техническая возможность оставить точку возврата из раздела выше, и единственный способ это проверить — сравнить состояние сервера с тем, что было до начала работ.

Чек-лист аудита, который стоит проходить как обязательный пункт закрытия задачи, а не опционально:

  • [ ] Все authorized_keys на сервере, включая root и deploy-аккаунты, не только выданный:
for f in /home/*/.ssh/authorized_keys /root/.ssh/authorized_keys; do
  echo "== $f =="; cat "$f" 2>/dev/null
done
  • [ ] Пользователи с UID 0 помимо самого root:
awk -F: '$3 == 0 {print}' /etc/passwd
  • [ ] Список системных пользователей сверх ожидаемого:
getent passwd | awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $3}'
  • [ ] Правила sudo — всё, что появилось в /etc/sudoers.d/ за время работы подрядчика:
sudo ls -la /etc/sudoers.d/
grep -r NOPASSWD /etc/sudoers /etc/sudoers.d/ 2>/dev/null
  • [ ] Cron-задачи и systemd-таймеры для всех пользователей, не только для аккаунта подрядчика:
for u in $(cut -f1 -d: /etc/passwd); do crontab -u "$u" -l 2>/dev/null && echo "^ $u"; done
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/
systemctl list-timers --all
  • [ ] Setuid-бинарники, сравнённые со списком до начала работ:
find / -xdev -perm -4000 -type f 2>/dev/null
  • [ ] Открытые сетевые порты, не соответствующие ожидаемому набору сервисов:
ss -tlnp

Практический совет, который сильно облегчает этот шаг: снимите тот же набор данных (пользователи, ключи, cron, sudoers, setuid-файлы) до того, как подрядчик впервые получил доступ, и сохраните снимок отдельно, вне сервера. Тогда аудит превращается не в "искать что-то подозрительное на глаз", а в сравнение двух списков — что появилось нового. Разница в реальном времени на проверку огромная, особенно если сервер обслуживает не один проект. Методика прогона такой проверки сразу по нескольким серверам разобрана в статье про аудит authorized_keys за час.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Если подрядчика порекомендовали знакомые и он давно на рынке — эти меры всё равно нужны?

Да, дело не в подозрении лично к нему. Хороший специалист с безупречной репутацией всё равно может ошибиться, быть скомпрометирован через свой ноутбук, или просто забыть что-то за собой — временная учётка и постаудит защищают от этого ровно так же, как от гипотетического злого умысла. Общий скрининг доверия к человеку — отдельная задача, разобранная в статье 15 вопросов фрилансеру-администратору до оплаты; эта статья про другое — что делать с самим фактом выдачи root, независимо от степени доверия.

Сколько времени реально занимают все эти меры на практике?

Ограничение sudo и создание временной учётки — обычно 10-15 минут, меньше, чем согласование самой задачи. Пересылка логов на отдельный сервер — разовая настройка на весь парк, а не на каждого подрядчика. Постаудит по чек-листу выше — 15-30 минут на сервер, быстрее при наличии снимка состояния "до".

Что если подрядчику реально нужен root, и обойтись точечным sudo никак нельзя?

Используйте оставшиеся три меры в полном объёме: срок действия учётки, логирование с пересылкой за пределы сервера, обязательный аудит после. Риск это не устраняет полностью — при root устранить его целиком невозможно в принципе — но заметно снижает и вероятность незамеченного злоупотребления, и масштаб последствий.

Мы уже выдали root месяц назад без каких-либо из этих мер — есть смысл спохватываться сейчас?

Да, аудит имеет смысл провести в любой момент — чем раньше обнаружена забытая точка доступа, тем короче окно, в течение которого ею можно было воспользоваться. Пройдите чек-лист из последнего раздела прямо сейчас, не дожидаясь формального закрытия задачи.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →