Я корень. Я хотел бы знать, есть ли у пользователя без полномочий root права на запись в некоторые файлы - тысячи из них. Как сделать это эффективно, избегая создания процесса?
shell
files
permissions
users
Говард
источник
источник
access(2)
с соответствующим образом установленным реальным UID (например, черезsetresuid(2)
или портативный эквивалент)? Я имею в виду, мне было бы тяжело сделать это из bash, но я уверен, что Perl / Python справится с этим.[ -w
обычно используют access (2) или эквивалентный. Вы также должны установить gids в дополнение к uid (как su или sudo). Bash не имеет встроенной поддержки для этого, но Zsh делает.chgrp
в любой оболочке.Ответы:
Возможно, вот так:
Вышеуказанное запускает одну внешнюю программу для каждого файла, а именно
stat(1)
.Примечание: это предполагает
bash(1)
и воплощение Linuxstat(1)
.Примечание 2: Пожалуйста, прочитайте комментарии Стефана Шазеля ниже для прошлого, настоящего, будущего и потенциальных опасностей и ограничений этого подхода.
источник
-
. Вместо этого вы можете изменить его так, чтобы он принимал список с разделителями NUL, используяread -d ''
util-linux
), которые специально написаны для Linux,stat
вы не имеете в виду, это команда GNU, которая была перенесена на большинство систем, а не только на Linux. Также обратите внимание, что у вас былаstat
команда в Linux задолго до того, какstat
была написана GNU (stat
встроенная команда zsh).stat(1)
». Я имею в виду тот,stat(1)
который принимает-c <format>
синтаксис, а не, скажем, синтаксис BSD-f <format>
. Я также считаю, что это было довольно ясно, я не имел в видуstat(2)
. Я уверен, что страница вики об истории общих команд была бы довольно интересной.TL; DR
Вам нужно спросить систему, есть ли у пользователя разрешение на запись. Единственный надежный способ - переключить эффективный uid, эффективный gid и gid дополнения на пользовательский и использовать
access(W_OK)
системный вызов (даже если это имеет некоторые ограничения для некоторых систем / конфигураций).И имейте в виду, что отсутствие разрешения на запись в файл не обязательно гарантирует, что вы не сможете изменить содержимое файла по этому пути.
Длинная история
Давайте рассмотрим , что требуется, например , для $ пользователю иметь доступ на запись
/foo/file.txt
(предполагая , ни один из/foo
и/foo/file.txt
символические ссылки)?Он нуждается:
/
(не нужноread
)/foo
(не нужноread
)/foo/file.txt
Вы уже можете видеть, что подходы (например, @ lcd047 или @ apaul ), которые проверяют только разрешение «
file.txt
не работает», потому что они могут сказать,file.txt
что доступно для записи, даже если у пользователя нет разрешения на поиск/
или/foo
.И такой подход, как:
Также не будет работать, потому что он не будет сообщать о файлах в каталогах, которые пользователь не имеет права на чтение (
find
поскольку он$user
не может перечислить их содержимое), даже если он может писать в них.Если мы забудем о ACL, файловых системах только для чтения, флагах FS (например, неизменяемых), других мерах безопасности (apparmor, SELinux, которые могут даже различать различные типы записи) и сосредоточимся только на традиционных атрибутах прав доступа и владения, чтобы получить дано (поиск или запись) разрешение, это уже довольно сложно и трудно выразить
find
.Тебе нужно:
В
find
синтаксисе, в качестве примера с пользователем uid 1 и gids 1 и 2, это будет:Тот удаляет каталоги, которые пользователь не имеет права на поиск и для других типов файлов (символические ссылки исключены, поскольку они не релевантны), проверяет доступ на запись.
Если вы также хотите рассмотреть возможность записи в каталоги:
Или для произвольного
$user
и его членства в группе, полученного из пользовательской базы данных:(это 3 процесса в общем:
id
,sed
иfind
)Лучше всего было бы спускаться по дереву от имени пользователя root и проверять права доступа для каждого файла.
(это один
find
процесс плюс одинsudo
иsh
обрабатывать каждые несколько тысяч файлов,[
иprintf
, как правило , построены в оболочке).Или с
perl
:(3 процессы в общей сложности :
find
,sudo
иperl
).Или с
zsh
:(Всего 0 процессов, но весь список файлов сохраняется в памяти)
Эти решения основаны на
access(2)
системном вызове. То есть вместо того, чтобы воспроизводить алгоритм, который система использует для проверки прав доступа, мы просим систему выполнить эту проверку с помощью того же алгоритма (который учитывает права доступа, ACL, неизменяемые флаги, файловые системы только для чтения ...) ) он будет использовать, если вы попытаетесь открыть файл для записи, так что вы ближе всего найдете надежное решение.Чтобы протестировать решения, приведенные здесь, с различными комбинациями пользователей, групп и разрешений, вы можете сделать:
Изменение пользователя от 1 до 2 и группы между 1, 2 и 3 и ограничение 9 младшими битами разрешений, так как это уже 9458694 созданных файлов. Это для каталогов, а затем снова для файлов.
Это создает все возможные комбинации
u<x>g<y>/<mode1>/u<z>g<w>/<mode2>
. Пользователь с uid 1 и gids 1 и 2 будет иметь доступ для записи,u2g1/010/u2g3/777
но неu1g2/677/u1g1/777
например.Теперь все эти решения пытаются определить пути к файлам, которые пользователь может открыть для записи, это отличается от путей, по которым пользователь может изменять содержимое. Чтобы ответить на этот более общий вопрос, необходимо принять во внимание несколько вещей:
/a/b/file
но если он владеетfile
(и имеет доступ к поиску/a/b
, и файловая система не доступна только для чтения, и у файла нет неизменяемого флага, и у него есть доступ оболочки к системе), тогда он сможет изменить права доступаfile
и предоставить себе доступ./a/b
но не имеет доступа к поиску./a/b/file
потому что у него нет доступа к поиску/a
или/a/b
, но этот файл может иметь жесткую ссылку,/b/c/file
например, в этом случае он может изменить содержимое/a/b/file
, открыв его по его/b/c/file
пути./a
, но/a/b
может быть привязан к нему/c
, поэтому он может открытьсяfile
для записи по/c/file
другому пути./a/b/file
, но если у него есть доступ для записи,/a/b
он может удалить или переименовать егоfile
и заменить его своей собственной версией. Он изменил бы содержимое файла на/a/b/file
даже если это был бы другой файл./a
(он мог бы переименовать/a/b
в/a/c
, создать новый/a/b
каталог и новыйfile
в нем.Чтобы найти пути,
$user
которые можно было бы изменить. По адресу 1 или 2 мы больше не можем полагаться наaccess(2)
системный вызов. Мы могли бы изменить нашfind -perm
подход, чтобы разрешить поиск по каталогам или записать доступ к файлам, как только вы станете владельцем:Мы могли бы обратиться к 3 и 4, записав номера устройств и индексов или все файлы, которые $ user имеет разрешение на запись, и сообщать обо всех путях к файлам, которые имеют эти номера dev + inode. На этот раз мы можем использовать более надежный
access(2)
подходы:Что-то типа:
5 и 6 на первый взгляд усложняются
t
битом разрешений. При применении к каталогам это бит ограниченного удаления, который не позволяет пользователям (кроме владельца каталога) удалять или переименовывать файлы, которые им не принадлежат (даже если они имеют доступ для записи в каталог).Например, если мы вернемся к нашему предыдущему примеру, если у вас есть доступ к записи
/a
, то вы должны быть в состоянии переименовать/a/b
в/a/c
, а затем воссоздать/a/b
каталог и новымиfile
там. Но еслиt
бит включен,/a
а вы не являетесь владельцем/a
, то вы можете сделать это только при наличии/a/b
. Это дает:t
бит не установлен, и вы в том же случае, что и выше (все пути к файлам ваши).Таким образом, мы можем обратиться ко всем 1, 2, 5 и 6 с помощью:
Это и решение для 3 и 4 являются независимыми, вы можете объединить их вывод, чтобы получить полный список:
Как должно быть понятно, если вы уже все прочитали, часть этого, по крайней мере, касается только разрешений и владения, а не других функций, которые могут предоставлять или ограничивать доступ для записи (FS только для чтения, ACL, неизменяемый флаг, другие функции безопасности. ...). И поскольку мы обрабатываем ее в несколько этапов, часть этой информации может быть неправильной, если файлы / каталоги создаются / удаляются / переименовываются или изменяются их права доступа / владельца во время выполнения этого скрипта, как на занятом файловом сервере с миллионами файлов ,
Замечания о переносимости
Весь этот код является стандартным (POSIX, Unix для
t
бит), кроме:-print0
это расширение GNU, теперь также поддерживаемое несколькими другими реализациями. Сfind
реализациями, которые не поддерживают его, вы можете использовать-exec printf '%s\0' {} +
вместо этого и заменить-exec sh -c 'exec find "$@" -print0' sh {} +
на-exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +
.perl
не указана в POSIX, но широко доступна. Вам нужноperl-5.6.0
или выше для-Mfiletest=access
.zsh
не является командой, указанной в POSIX. Этотzsh
код выше должен работать с zsh-3 (1995) и выше.sudo
не является командой, указанной в POSIX. Код должен работать с любой версией, если конфигурация системы позволяет работатьperl
от имени данного пользователя.источник
x
разрешения на поиск ( бит) в каталоге. Вы также можете иметь разрешения на поиск, но не можете читать , то есть файлы там скрыты для вас, но если вы знаете их имя, вы можете получить к ним доступ. Типичным примером является каталог сессионного файла php (что-то вроде / var / lib / php).Вы можете объединить параметры с
find
командой, чтобы она обнаружила файлы с указанным режимом и владельцем. Например:Приведенная выше команда выведет список всех записей, которые принадлежат группе «штат» или «пользователи» и имеют разрешение на запись для этой группы.
Вам также следует проверить записи, которые принадлежат вашему пользователю, и файлы, которые доступны для записи всем пользователям, поэтому:
Однако эта команда не будет соответствовать записям с расширенным списком ACL. Таким образом, вы можете
su
узнать все записи для записи:источник
r-xrwxrwx yourusername:anygroup
или дляr-xr-xrwx anyone:staff
записи.yourusername
, не имеют доступа к ним.Подход зависит от того, что вы действительно тестируете.
Это потому, что есть много способов прийти к 2), и ответ Стефана хорошо их охватывает (непреложный - тот, который нужно запомнить), и напомним, что есть и физические средства, такие как размонтирование диска или создание его только для чтения на аппаратный уровень (флоппи-вкладки). Я предполагаю, что ваши тысячи файлов находятся в разных каталогах, и вы хотите отчет или вы проверяете по основному списку. (Еще одно злоупотребление Puppet просто ждет, чтобы случиться).
Вы, вероятно, захотите обход дерева Perl Стефана и, если потребуется, «объедините» вывод со списком (su также перехватит отсутствующее выполнение в родительских каталогах?). Если суррогатное материнство является проблемой производительности, вы делаете это для «большого количества» пользователей? Или это онлайн-запрос? Если это постоянное постоянное требование, возможно, пришло время рассмотреть сторонний продукт.
источник
Ты можешь сделать...
... для списка всех файлов, в которые пользователь не может записать, как записано в stderr в форме ...
...или похожие.
См. Комментарии ниже для замечаний по проблемам, которые может иметь этот подход, и объяснение ниже, почему он может работать. Более разумно, однако, вы должны, вероятно, только
find
обычные файлы, такие как:Короче говоря,
tee
будет печатать ошибки, когда он пытаетсяopen()
файл с любым из двух флагов ...... и встречи ...
... как указано здесь :
Потому что он должен проверить так же, как
test -w
делает ...Они оба проверяют доступность .
источник
tee
будет зависать, если явно не прерывается один раз за запуск. Это была самая близкая вещь, о которой я мог подумать[ -w
... хотя - ее эффекты должны быть близкими, так как она гарантирует, что пользователь сможет ОТКРЫТЬ файл. Гораздо проще, чем любой другой вариант,pax
с-o
параметрами формата и / или-t
для проверкиEACCESS
- но каждый раз, когда я предлагаю,pax
люди, кажется, игнорируют его. И, во всяком случае, единственное,pax
что я нашел, соответствует стандарту AST - в этом случае вы могли бы также использовать ихls
.