Linux и инструменты разработчика
Основы Bash для работы в безопасности
Пайпы, перенаправление, переменные, циклы, коды завершения и set -euo pipefail, а затем подсчёт неудачных входов и хеширование папки на этой основе.
Владельцы и группы в Linux, биты rwx, chmod, umask и setuid, а также лабораторная, где доступ проверяется от имени второго пользователя и ищутся опасные режимы файлов.
Права в Linux определяют, кто может читать, менять и запускать каждый файл в системе. Большинство проблем, которые встречаются на ревью безопасности, обходятся без экзотических эксплойтов: конфиг, в который может писать любой локальный аккаунт, скрипт, который запускает root-сервис, а редактировать может обычный пользователь, или бинарник с битом setuid, который никто не помнит, как добавлял. Эта статья собирает механизм снизу вверх: владельцы, группы, биты rwx, chmod, umask и специальные биты, которые важнее всего на ревью. Вы будете создавать файлы, менять их режимы, проверять доступ от имени второго локального пользователя в лабораторной VM и искать опасные права.
В основе лежит принцип наименьших привилегий. У процесса должен быть только тот доступ, который ему нужен, а писать в файл должны только люди и программы, которым положено его менять. Режимы файлов — первое место, где Linux применяет это правило, поэтому их и проверяют первыми.
У каждого файла и каталога есть три вещи, от которых зависит доступ:
Выполните это на любом файле в домашнем каталоге:
ls -l notes.txtПервый символ — тип файла (- обычный файл, d каталог, l символическая ссылка). Следующие девять символов — режим. Имена владельца и группы идут после счётчика ссылок.
Ядро проверяет права каждый раз, когда процесс открывает файл. Оболочка, веб-сервер и задача cron проходят одну и ту же проверку. Если она не пройдена, вы получаете Permission denied. Файловой системе всё равно, доверенный процесс или нет.
В режиме три триплета, по одному на каждый класс пользователей:
Linux проверяет классы по порядку. Если ваш аккаунт владелец, применяются биты владельца, а биты группы и остальных игнорируются, даже если они дали бы больше прав. Многих это удивляет. Файл с битами владельца --- не откроется для своего владельца, даже если биты группы равны rwx и владелец в этой группе состоит.
Членство в группах хранится отдельным списком. Своё можно проверить так:
id
groupsИзменение членства в группе обычно вступает в силу при следующем входе. В оболочке, где вы выполнили команду, оно ещё не действует.
В каждом триплете три бита:
| Бит | На обычном файле | На каталоге |
|---|---|---|
r (чтение, значение 4) |
Читать содержимое | Видеть список имён внутри |
w (запись, значение 2) |
Менять содержимое | Создавать, переименовывать и удалять записи |
x (выполнение, значение 1) |
Запускать как программу | Входить в каталог и обращаться к его записям |
На двух вещах часто спотыкаются новички.
Во-первых, проходить через каталог позволяет его бит x. В каталоге с r без x видны имена, но открыть их нельзя. В каталоге с x, но без r можно открыть файл, точное имя которого вы уже знаете, а получить список нельзя.
Во-вторых, право записи в файл не даёт права его удалить. Удаление зависит от прав записи и выполнения на каталоге, где лежит запись. Файл, которым вы владеете, в каталоге без права записи удалить не получится.
chmod принимает две записи одного и того же.
Восьмеричная. Каждый триплет превращается в одну цифру, сумму его битов: r равен 4, w равен 2, x равен 1. Значит, rw- это 6, r-- это 4, r-x это 5, а rwx это 7. Режим 644 означает чтение и запись для владельца (6), чтение для группы (4), чтение для остальных (4). Режим 600 означает, что читать и писать может только владелец.
Символьная. Вы указываете класс, оператор и биты:
u (владелец), g (группа), o (остальные), a (все). Если класс не указан, подразумевается a, но биты umask при этом не затрагиваются.+ добавляет биты, - убирает их, = выставляет в классе ровно эти биты и сбрасывает остальные.Так, chmod u=rw,go=r notes.txt даёт тот же результат, что и chmod 644 notes.txt. chmod g+w notes.txt добавляет запись для группы и не трогает остальные биты.
Восьмеричная запись компактна, и её удобно вставлять в скрипты. Символьная безопаснее для одиночного изменения, потому что не стирает биты, о которых вы не подумали. На ревью ждите обе, в файлах управления конфигурацией, Dockerfile и установочных скриптах.
chmod меняет режим. Успешно выполнить его на файле может только владелец или root. Остальные получат Operation not permitted.
Безопасная привычка — прочитать режим, изменить его и прочитать снова:
stat -c '%a %A %U:%G %n' notes.txt
chmod 600 notes.txt
stat -c '%a %A %U:%G %n' notes.txtstat -c печатает восьмеричный режим (%a), символьный режим (%A), имена владельца и группы (%U, %G) и имя файла (%n). Этот формат будет использоваться на всей лабораторной.
chown меняет владельца, а chgrp меняет группу. Для передачи файла другому пользователю обычно нужен root. Не запускайте chown -R на дереве, пока не посмотрите, что будет затронуто.
Создавая файл, программа запрашивает начальный режим. Для обычного файла это 666, для каталога 777. umask убирает биты из этого начального значения. Его устанавливает оболочка, и через него проходит каждый файл и каталог, который создают оболочка и её дочерние процессы.
В большинстве дистрибутивов Linux значение по умолчанию равно 022. Для файла 666 минус 022 даёт 644, поэтому новые файлы получают rw-r--r--. Для каталога 777 минус 022 даёт 755, поэтому новые каталоги получают rwxr-xr-x. umask только убирает права. Режим никогда не станет шире начального значения.
Проверьте своё значение:
umaskБолее строгий umask вроде 077 даёт файлы 600 и каталоги 700, доступные только владельцу. Более свободный вроде 002 даёт файлы 664 и каталоги 775, в которые может писать группа. umask, заданный в профиле оболочки, действует на эту оболочку и её дочерние процессы. На уже существующие файлы он не влияет.
Четырёхзначные восьмеричные режимы добавляют первую цифру для трёх специальных битов:
/tmp.ls -l показывает setuid как s в позиции выполнения владельца, а sticky как t в позиции выполнения остальных. В Ubuntu 24.04 строка для passwd выглядит так:
-rwsr-xr-x 1 root root 64152 May 30 2024 /usr/bin/passwdПрограммам вроде passwd нужен setuid, потому что они записывают защищённые файлы учётных записей от имени обычного пользователя. Риск в том, что каждый setuid-бинарник root даёт обычному пользователю выполнять код с правами root. Баг в одном из них, например повреждение памяти или небезопасный вызов вспомогательной программы, может привести к локальному повышению привилегий. Ревьюеры ведут короткий список setuid-бинарников и сравнивают его с известным эталоном. Новый setuid-файл, который никто намеренно не устанавливал, — находка, на которую нужен ответ.
Другая частая проблема — файлы, доступные на запись всем. Файл с o+w может изменить любой локальный аккаунт. Если это скрипт, конфиг, который читает root-сервис, или бинарник в каталоге из PATH, эксплойт атакующему не нужен. Он просто редактирует файл. Проверяйте и каталоги. Доступный на запись каталог на пути, который использует root, может позволить атакующему заменить файл, даже если сам файл закрыт.
Выполняйте это в среде Linux под вашим контролем: в дистрибутиве WSL или в VM, созданной для этого курса. Не запускайте на продакшен-сервере или общей машине. Раздел со вторым пользователем создаёт аккаунт, поэтому выполняйте его только в своей лабораторной VM.
mkdir ~/permlab && cd ~/permlab
echo 'lab secret' > notes.txt && ls -l notes.txtВ Ubuntu 24.04 под WSL новый файл показал -rw-r--r--, а владелец и группа были названы по имени аккаунта. Ваши имя пользователя, дата и группа будут другими. Сравнивайте режим.
chmod 600 notes.txt && stat -c '%a %U:%G %n' notes.txt
umaskПолученный вывод:
600 usurio:usurio notes.txt
0022Имя вашего аккаунта будет другим. 600 означает, что читать и писать может только владелец. 0022 — это umask в текущей оболочке, и ведущий ноль входит в восьмеричную запись.
Теперь каталог:
mkdir sub && chmod 750 sub && stat -c '%a %n' subРезультат: 750 sub. У владельца полный доступ, группа может читать и входить, у остальных нет ничего.
Символьные изменения, по одному, с чтением после каждого:
chmod u=rw,go=r notes.txt && stat -c '%a %A %n' notes.txt
chmod g+w notes.txt && stat -c '%a %A %n' notes.txt
chmod o-r notes.txt && stat -c '%a %A %n' notes.txtВывод:
644 -rw-r--r-- notes.txt
664 -rw-rw-r-- notes.txt
660 -rw-rw---- notes.txtКаждая команда изменила только те биты, которые указаны в ней.
Запускайте umask в подоболочке, чтобы изменение не осталось в сессии:
(umask 077; touch private.txt; stat -c '%a %A %n' private.txt)
(umask 002; touch shared.txt; mkdir made_dir; stat -c '%a %A %n' shared.txt made_dir)Вывод:
600 -rw------- private.txt
664 -rw-rw-r-- shared.txt
775 drwxrwxr-x made_dirС 077 файл потерял все биты группы и остальных. С 002 группа получила запись и на файл, и на каталог. Каталог начинался с 777 и потерял только 002.
Для этого шага нужен аккаунт, который можно создать в своей VM. Выполняйте его только там.
sudo useradd -m labuser
sudo -u labuser cat ~/permlab/notes.txtЭти команды я не запускал: аккаунту WSL нужен пароль для sudo, а его я не вводил. На что смотреть: при режиме 600 вторая команда должна завершиться сообщением Permission denied, потому что labuser не владелец и не входит в группу.
Теперь ослабьте права файла для остальных:
chmod 644 notes.txt
sudo -u labuser cat ~/permlab/notes.txtНа что смотреть: содержимое напечатается, только если labuser может войти и в ваш домашний каталог, и в ~/permlab. Многие дистрибутивы создают домашние каталоги с 755, но некоторые используют 750. Если родительский каталог не даёт x остальным, чтение всё равно не удастся, даже если файл доступен для чтения. Проверьте с помощью ls -ld ~ ~/permlab. В установке Ubuntu 24.04 на WSL, которой я пользовался, ls -ld ~ напечатал drwxr-x---, то есть 750, поэтому второй пользователь был бы заблокирован и после chmod 644. Это тот самый бит x каталога на практике.
Выведите обычные файлы в домашнем каталоге, доступные на запись всем, не переходя на другие файловые системы:
find ~ -xdev -type f -perm -o+w 2>/dev/nullВ чистой лаборатории это ничего не выведет. Чтобы увидеть поиск в работе, намеренно откройте один файл на запись:
chmod 666 ~/permlab/notes.txt
find ~ -xdev -type f -perm -o+w 2>/dev/null
chmod 644 ~/permlab/notes.txtРезультат: первый поиск напечатал /home/usurio/permlab/notes.txt. После исправления тот же поиск ничего не напечатал.
Выведите setuid-бинарники в системном каталоге:
find /usr/bin -perm -4000 -type f 2>/dev/null | sortВ Ubuntu 24.04 под WSL команда напечатала десять файлов, среди них /usr/bin/passwd, /usr/bin/sudo, /usr/bin/su, /usr/bin/mount и /usr/bin/umount. Ваш список зависит от дистрибутива и установленных пакетов. На ревью сравнивайте список с тем, что по данным менеджера пакетов должно иметь setuid. Неожиданную запись считайте вопросом, на который нужен ответ. Доказательством атаки она ещё не служит.
Проверьте sticky-бит на временных каталогах:
stat -c '%a %A %n' /tmp /var/tmpРезультат: 1777 drwxrwxrwt для обоих. t означает, что пользователи могут создавать там файлы, но не могут удалять чужие.
rm -rf ~/permlab
sudo userdel -r labuseruserdel -r удаляет и домашний каталог аккаунта. Запускайте это только для созданного вами лабораторного аккаунта.
Те же первые шаги в Git Bash для Windows вели себя не так, как в Linux. После chmod 600 notes.txt команда stat по-прежнему показывала 644, и следующие вызовы chmod вывод тоже не меняли. Windows хранит доступ в списках управления доступом NTFS, а Git Bash сопоставляет только часть битов. Лабораторная в Windows научит командам, но не покажет, что делает режим Linux. Для этой статьи используйте WSL с дистрибутивом Linux или VM.
777 как решение отказа в доступе. Это работает, но разрешает всем писать в файл и выполнять его. Найдите, какому классу отказано, и дайте права только ему.
Забытый каталог. Доступный на чтение файл может оказаться недостижимым, если у родительского каталога нет x для этого пользователя. Проверяйте каждый каталог на пути.
chmod -R на всём дереве. Рекурсивные изменения часто выставляют выполнение обычным файлам или убирают его у каталогов. Чтобы выбрать один тип, используйте find с -type f или -type d.
Доверие режиму скопированного файла. cp, tar и архиваторы могут сохранять или сбрасывать режимы в зависимости от флагов. Проверяйте результат с помощью stat.
Чтение символьных режимов как абсолютных. chmod g+w добавляет один бит. chmod g=w сбрасывает чтение и выполнение для группы. Разницу легко проглядеть.
Первым делом root. Многие проблемы с чтением и записью решаются членством в группе или режимом каталога, setuid-хелпер или root-оболочка для них не нужны.
Ревью прав начинается с одного вопроса: кто может изменить то, что читает или запускает привилегированный процесс? Снова и снова встречаются три находки:
Описывая находку, укажите путь, режим, владельца, группу, процесс, который читает или запускает файл, и изменение, которое всё исправляет. Тестируйте в своей лаборатории. Не запускайте эти поиски на системах, которые вы не администрируете, и не используйте sudo -u на чужой машине.
Когда базовые режимы станут понятны, изучите списки управления доступом с getfacl и setfacl, они добавляют записи для отдельных пользователей сверх владельца, группы и остальных. Прочитайте руководство chattr о флагах immutable и append-only. Используйте namei -l /path/to/file, чтобы напечатать режим каждого компонента пути. Так быстрее всего найти каталог, который блокирует сервис.
Чтобы освоить привычки работы в оболочке, на которых держатся эти команды, начните с более ранней статьи Полевого руководства Основы Bash для студентов по безопасности. Следующая статья, что такое SSH и как работают SSH-ключи, рассказывает о ключах SSH, которые зависят от тех же режимов: файл приватного ключа должен быть доступен на чтение только владельцу, а клиент SSH откажется использовать ключ со слишком открытым режимом.
Наименьшие привилегии начинаются с режимов файлов. Процесс, который может писать меньше, причиняет меньше вреда, когда ошибается, а файл, который не могут изменить другие, можно не проверять лишний раз.
Linux и инструменты разработчика
Пайпы, перенаправление, переменные, циклы, коды завершения и set -euo pipefail, а затем подсчёт неудачных входов и хеширование папки на этой основе.
Linux и инструменты разработчика
Как работают ключи хоста и пользователя в SSH, почему по умолчанию стоит брать Ed25519 с парольной фразой и как настроить и защитить вход по ключу на своей лабораторной VM.
Linux и инструменты разработчика
GitHub для начинающих: что делают Git и GitHub, какие термины нужны, локальная практика с Git и как проверить проект перед запуском.