Используя сгенерированный список имен файлов как список аргументов — с пробелами

"Для взломщика действительно ли возможно сделать sudo или gksudo без подсказки пароля, прежде чем пароль истечет, и примите мою систему?"

Да.

Самое легкое нападение прибывает из интерактивной оболочки и Вас не блокировка Вашего экрана, когда Вы убегаете от своей клавиатуры.

Если Вы волнуетесь, то изменяете строку

Defaults        timestamp_timeout=90

в Вашем /etc/sudoers, это изменяет 5-минутный тайм-аут.

16
21.01.2014, 01:38
5 ответов

Вы могли сделать следующее использование некоторых реализаций find и xargs как это.

$ find . -type f -print0 | xargs -r0 ./myscript

или, стандартно, просто find:

$ find . -type f -exec ./myscript {} +

Пример

Скажите, что у меня есть следующий демонстрационный каталог.

$ tree
.
|-- dir1
|   `-- a\ file1.txt
|-- dir2
|   `-- a\ file2.txt
|-- dir3
|   `-- a\ file3.txt
`-- myscript

3 directories, 4 files

Теперь скажем, у меня есть это для ./myscript.

#!/bin/bash

for i in "$@"; do
    echo "file: $i"
done

Теперь, когда я выполняю следующую команду.

$ find . -type f -print0 | xargs -r0 ./myscript 
file: ./dir2/a file2.txt
file: ./dir3/a file3.txt
file: ./dir1/a file1.txt
file: ./myscript

Или когда я использую 2-ю форму как так:

$ find . -type f -exec ./myscript {} +
file: ./dir2/a file2.txt
file: ./dir3/a file3.txt
file: ./dir1/a file1.txt
file: ./myscript

Подробнее

найдите + xargs

Вышеупомянутые 2 метода, хотя выглядя по-другому, являются по существу тем же. Первое берет вывод от находки, разделяя его, использование АННУЛИРУЕТ (\0) через -print0 переключитесь для нахождения. xargs -0 специально предназначено для взятия входа, это разделило использование, АННУЛИРУЕТ. Тот нестандартный синтаксис был представлен GNU find и xargs но также найден в наше время в немногих других как новый BSDs. -r опция требуется, чтобы не звонить myscript если find ничего не находит с GNU find но не с BSDs.

Примечание: Этот весь подход зависит от того, что Вы никогда не будете передавать строку, это чрезвычайно длинно. Если это, то 2-й вызов ./myscript будет начат с остатком от последующих результатов, находят.

найдите с +

Это - стандартный путь (хотя он был только добавлен относительно недавно (2005) к реализации GNU find). Способность сделать то, с чем мы делаем xargs буквально создается в find. Так find найдет список файлов и затем передаст тот список так как многие аргументы, как может соответствовать к команде, указанной после -exec (отметьте это {} может только быть последним незадолго до + в этом случае), выполняя команды несколько раз в случае необходимости.

Почему никакое заключение в кавычки?

В первом примере мы срезаем путь путем завершенного предотвращения проблем с заключением в кавычки, при помощи ПУСТЫХ УКАЗАТЕЛЕЙ для разделения аргументов. Когда xargs дан этот список, который это проинструктировано для разделения на ПУСТЫХ УКАЗАТЕЛЯХ, эффективно защищающих наши отдельные атомы команды.

Во втором примере мы сохраняем результаты внутренними к find и таким образом, это знает то, что каждый атом файла и гарантирует, что обработал их соответственно, таким образом, избегая целого бизнеса заключения в кавычки их.

Максимальный размер командной строки?

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

$ xargs --show-limits
Your environment variables take up 4791 bytes
POSIX upper limit on argument length (this system): 2090313
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2085522
Size of command buffer we are actually using: 131072
12
27.01.2020, 19:48
  • 1
    Спасибо, но я должен передать все аргументы тому же вызову моего сценария. Это находится в описании проблемы, но я предполагаю, что не прояснил, что это не случайный факт. –  alexis 20.01.2014, 03:09
  • 2
    @alexis - читают ответы снова, они передают все аргументы единственному вызову Вашего сценария. –  slm♦ 20.01.2014, 03:15
  • 3
    я буду проклят! Я не знал о + аргумент find (и Вы используете + в прозе также, таким образом, я пропустил Ваше объяснение в первый раз). Но главное, я неправильно понял что xargs делает по умолчанию!!! За три десятилетия использования Unix у меня никогда не было использования для него до сих пор, но я думал, что знал свою панель инструментов... –  alexis 20.01.2014, 03:27
  • 4
    @alexis - я полагал, что Вы пропустили то, что мы говорили. Да xargs дьявол команды. Необходимо считать его и findстраницы справочника много раз к grok, что они могут сделать. May переключателей является положительными сторонами мятежника друг друга так, чтобы добавил к беспорядку. –  slm♦ 20.01.2014, 03:32
  • 5
    @alexis - также еще одна вещь добавить к панели инструментов, не используйте одинарные левые кавычки/обратные галочки для выполнения вложенных команд, используйте $(..) теперь вместо этого. Это автоматически обрабатывает вложение кавычек и т.д. Обратные галочки удерживаются от использования. –  slm♦ 20.01.2014, 03:34
find . -name something.txt -exec myscript {} +

В вышеупомянутом, find находит все имена файлов соответствия и обеспечивает их как аргументы myscript. Это работает с именами файлов независимо от пробелов или любых других нечетных символов.

Если все соответствие имен файлов на одной строке, то myscript выполняется однажды. Если список будет слишком длинным, чтобы оболочка обработала, то находка выполнит myscript многократно по мере необходимости.

Еще: Сколько файлов соответствует на командной строке? man find говорит это find сборки это командные строки "почти такой же способ, которым xargs создает его". И, man xargs то, что пределы системно-зависимы и что можно определить их путем выполнения xargs --show-limits. (getconf ARG_MAX также возможность). На Linux предел обычно является (но не всегда) приблизительно 2 миллионами символов на командную строку.

3
27.01.2020, 19:48

Некоторые дополнение к прекрасному ответу @slm.

Ограничение на размер аргументов идет execve(2) системный вызов (на самом деле, это находится на кумулятивном размере аргумента и строк среды и указателей). Если myscript записан на языке, который может интерпретировать Ваша оболочка, затем возможно, Вы не должны выполнять ее, у Вас могла быть своя оболочка, просто интерпретируют его, не имея необходимость выполнять другой интерпретатор.

Если Вы запускаете скрипт как:

(. myscript x y)

Это похоже:

myscript x y

За исключением того, что это интерпретируется ребенком текущей оболочки, вместо того, чтобы выполнить его (который в конечном счете включает выполнение sh (или независимо от того, что строка хижины указывает если таковые имеются) еще с большим количеством аргументов).

Теперь, очевидно, Вы не можете использовать find -exec {} + с . команда, как . будучи встроенной командой оболочки, это должно быть выполнено оболочкой, не find.

С zsh, это легко:

IFS=$'\0'
(. myscript $(find ... -print0))

Или:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Хотя с zsh, Вам не было бы нужно find во-первых, поскольку большинство его функций создается в zsh globbing.

bash переменные однако не могут содержать символы NUL, таким образом, необходимо найти иначе. Один путь мог быть:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

Вы могли бы также использовать zsh-стиль рекурсивный globbing с с globstar опция в bash 4.0 и позже:

shopt -s globstar failglob dotglob
(. myscript ./**/something.txt)

Отметьте это ** сопровождаемые символьные ссылки на каталоги, пока это не было зафиксировано в bash 4.3. Также отметьте это bash не реализует zsh спецификаторы globbing, таким образом, Вы не получите все функции find там.

Другая альтернатива должна была бы использовать GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

Вышеупомянутые методы могут также использоваться, если Вы хотите удостовериться myscript выполняется только однажды (сбой, если список аргументов является слишком большим). На последних версиях Linux можно повысить и даже снять то ограничение на список аргументов с:

ulimit -s 1048576

(1 ГиБ складывает размер, четверть которого может использоваться для списка arg+env).

ulimit -s unlimited

(никакой предел)

2
27.01.2020, 19:48

В большинстве систем существует предел на длину командной строки, переданной любой программе, с помощью xargs или -exec command {} +. От man find:

-exec command {} +
      This  variant  of the -exec action runs the specified command on
      the selected files, but the command line is built  by  appending
      each  selected file name at the end; the total number of invoca‐
      tions of the command will  be  much  less  than  the  number  of
      matched  files.   The command line is built in much the same way
      that xargs builds its command lines.  Only one instance of  `{}'
      is  allowed  within the command.  The command is executed in the
      starting directory.

Вызовы будут намного меньше, но не гарантированы быть тем. То, что необходимо сделать, читается, NUL разделил имена файлов в сценарии от stdin, возможного на основе параметра командной строки -o -. Я сделал бы что-то как:

$ find . -name something.txt -print0 | myscript -0 -o -

и реализуйте аргументы опции myscript соответственно.

1
27.01.2020, 19:48
  • 1
    Да, ОС накладывает ограничение в числе/размере аргументов, которые могут быть переданы. В современных системах Linux это является (гигантским) (linux.die.net/man/2/execve) (1/4 размера стека, 0x7FFFFFFF аргументы). Сам удар AFAIK не накладывает ограничения. Мои списки являются значительно уменьшенными, и моя проблема была вызвана путем недоразумения или неправильного запоминания как xargs работы. Ваше решение является действительно самым устойчивым, но это - излишество в этом случае. –  alexis 20.01.2014, 12:06

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


От: http://www.fvwm.org/documentation/manpages/stable/FvwmTaskBar.php

При запуске панель задач отображается как один ряд кнопок, заполняющих всю ширину экрана, но во время работы ее размер может быть изменен, чтобы вместить до 8 строк. Кроме того, если используется параметр AutoStick, панель задач автоматически позиционируется в верхней или нижней части экрана и может быть перемещена из одной позиции в другую при обычной операции перемещения.

Следующие параметры можно поместить в файл .fvwm2rc

* FvwmTaskBar: Указывает шрифт, используемый для окон часов и подсказок. Если этот параметр не указан, используется фиксированный шрифт.

-121--157556-

/etc/rc.d/rc.local

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

Вы также можете поместить все, что хотите, в скрипт init в каталоге/etc/init.d или соответствующем каталоге/etc/rc.d.

-121--150480-

Нет ли какого-либо способа защиты мест в спине (или $ (...)) Расширение?

Нет, нет. Почему это?

Баш не может знать, что должно быть защищено, а что нет.

В файле/канале Unix нет массивов. Это просто поток байтов. Команда в " или $ () выводит поток, который поглощает и обрабатывает как одну последовательность. В этом случае у вас есть только два выборе: поместить его в кавычки, сохранить его в виде одной последовательности или поставить голым, чтобы bash разделил его в соответствии с настроенным поведением.

Поэтому, если требуется массив, необходимо определить байтовый формат, который имеет массив, и это то, что делают такие инструменты, как xargs и find : Если они запускаются с аргументом -0 , они работают в соответствии с двоичным форматом массива, который завершает элементы нулевым байтом, добавляя семантику к непрозрачному потоку байтов.

К сожалению, bash не может быть настроен для разделения последовательностей на пустой байт. Спасибо https://unix.stackexchange.com/a/110108/17980 за то, что показали нам, что zsh может.

xargs

Вы хотите, чтобы команда выполнялась один раз, и вы сказали, что xargs -0 -n 10000 решает вашу проблему. Это не означает, что при наличии более 10000 параметров команда будет выполняться более одного раза.

Если вы хотите, чтобы оно выполнялось только один раз или завершилось неуспешно, вы должны предоставить аргумент -x и аргумент -n , больший, чем аргумент -s (действительно: достаточно большой, чтобы целая куча нулевыхаргументы length плюс имя команды не помещаются в размер -s ). ( man xargs , см. выдержку ниже)

Система, в которой я в настоящее время нахожусь, имеет стек, ограниченный примерно 8M, поэтому мой предел:

$ printf '%s\0' -- {1..1302582} | xargs -x0n 2076858 -s 2076858 /bin/true
xargs: argument list too long
$ printf '%s\0' -- {1..1302581} | xargs -x0n 2076858 -s 2076858 /bin/true
(no output)

bash

Если вы не хотите использовать внешнюю команду, цикл чтения, питающий массив, как показано в https://unix.stackexchange.com/a/110108/17980 , является единственным путем для bash разделить вещи в нулевом байте

Идея источника сценария (.... «$ @») , чтобы избежать ограничения размера стека - это круто (я попробовал, это работает!), но, вероятно, не важно для обычных ситуаций.

Использование специального fd для технологической трубы важно, если вы хотите прочитать что-то другое из stdin, но в противном случае вам это не понадобится.

Итак, самый простой «родной» способ, для повседневных бытовых нужд:

files=()
while IFS= read -rd '' file; do
    files+=("$file")
done <(find ... -print0)

myscriptornonscript "${files[@]}"

Если вам нравится ваше дерево процессов чистым и хорошим для просмотра, этот метод позволяет сделать exec mynonscript «$ {files [@]}» , который удаляет процесс bash из памяти, заменяя его вызываемой командой. xargs всегда остается в памяти во время выполнения вызываемой команды, даже если команда будет выполняться только один раз.


Против собственного метода bash говорит то, что

$ time { printf '%s\0' -- {1..1302581} | xargs -x0n 2076858 -s 2076858 /bin/true; }

real    0m2.014s
user    0m2.008s
sys     0m0.172s

$ time {
  args=()
  while IFS= read -rd '' arg; do
    args+=( "$arg" )
  done < <(printf '%s\0' -- $(echo {1..1302581}))
  /bin/true "${args[@]}"
}
bash: /bin/true: Argument list too long

real    107m51.876s
user    107m38.532s
sys     0m7.940s

bash не оптимизирован для обработки массивов.


man xargs :

-n max-args

Используйте максимум аргументов max-args в командной строке. Меньше, чем аргументы max-args будут использоваться, если размер (см. параметр -s) превышено, если не задан параметр -x, в этом случае xargs выйдет.

-s max-chars

Используйте максимум символов max-chars в командной строке, включая команду и начальные аргументы и завершающие значения null на концах последовательностей аргументов. Наибольшее допустимое значение зависит от системы и рассчитывается как предел длины аргумента для exec, меньше размера среды, меньше 2048 байт свободного пространства. Если это значение больше 128KiB, 128Kib используется в качестве дефолт значение; в противном случае значение по умолчанию является максимальным. 1KiB составляет 1024 байта.

-x

Выход при превышении размера (см. параметр -s).

0
27.01.2020, 19:48

Теги

Похожие вопросы