На языке программирования я выполняю простую команду оболочки
cd var; echo > create_a_file_here
с переменной var , которая содержит строку (надеюсь) каталога, где я хочу создать файл "create_a_file_here". Теперь, если кто-то видит эту строку кода, можно использовать ее, назначив, например:
var = "; rm -rf /"
Вещи могут стать довольно уродливыми. Одним из способов избежать описанного выше случая может быть поиск строки в var для некоторых специальных символов, таких как ';' до выполнения команды оболочки, но я сомневаюсь, что это охватывает все возможные эксплойты.
Кто-нибудь знает хороший способ убедиться, что «cd var» только меняет каталог и ничего больше?
shell-script
shell
ES___
источник
источник
var
в качестве аргумента. Например вызовsh
с аргументами-c
,'cd "$1"; echo > create_a_file_here'
,'sh'
,var
работ и не требует каких - либо измененийvar
.'sh'
Аргумент передается как$0
.sh
или создаете свой собственный язык программирования с аналогичным синтаксисом, но который расширяетсяvar
вместо того, чтобы требовать от вас писатьcd "$var"
? Или этоbash
сshopt -s cdable_vars
? О, я думаю, вы имеете в виду, что какая-то другая программа разветвляет оболочку для выполнения этих команд. Так что просто цитируйтеvar
, но убедитесь, что он не содержит сам символ кавычки ...s='"'; echo "$s"
печатные издания"
.var=untrusted string
в родительской программе, такvar
что переменная окружения, которая уже установлена при вызовеsh
. Тогда вам просто нужно цитировать его каждый раз, когда вы расширяете его, что можно сделать надежно. Ах, я вижу, что идея уже является частью ответа Стефана>. <Ответы:
Если я правильно понимаю,
var
это переменная в вашем языке программирования.И на вашем языке программирования вы просите оболочку интерпретировать строку, которая является конкатенацией
"cd "
, содержимое этой переменной и"; echo > create_a_file_here"
.Если да, то если содержимое
var
не контролируется жестко, это уязвимость внедрения команд.Вы можете попробовать и правильно заключить в кавычки содержимое переменной¹ в синтаксисе оболочки, чтобы она гарантированно передавалась как один аргумент
cd
встроенной функции.Другой подход заключается в передаче содержимого этой переменной другим способом. Очевидным способом было бы передать это в переменную окружения. Например, в C:
На этот раз код, который вы просите интерпретировать оболочкой, исправлен, нам все еще нужно правильно написать его в синтаксисе оболочки (здесь предполагается, что это POSIX-совместимая оболочка):
-P
дляcd
сделать простойchdir()
--
отметить конец опций, чтобы избежать проблем сvar
запуском-
(или+
в некоторых оболочках)CDPATH
пустую строку в случае, если она находится в средеecho
команду только в случаеcd
успеха.Есть (по крайней мере) еще одна проблема: если она
var
есть-
, она не попадает в вызываемый каталог,-
а в предыдущий каталог (как хранится в$OLDPWD
) иOLDPWD=- CDPATH= cd -P -- "$DIR"
не гарантирует его обход. Так что вам нужно что-то вроде:¹ Обратите внимание , что только делает
это не путь, вы бы просто переместив проблему.system(concat("cd \"", var, "\"; echo..."));
Например,
var = "$(rm -rf /)"
все равно будет проблемой.Только надежный способ процитировать текст для Bourne-подобных оболочек заключается в одинарные кавычки , а также заботиться о одинарные кавычки , которые могут произойти в строке. Например, поверните
char *var = "ab'cd"
кchar *escaped_var = "'ab'\\''cd'"
. То есть замените все'
на'\''
и оберните все это внутри'...'
.Это по- прежнему предполагает , что эта строка в кавычках не используется в обратных кавычках, и вы по- прежнему нужно
--
,-P
,&&
,CDPATH=
...источник
Простое решение: не вызывайте оболочку из вашей программы. Совсем.
Ваш пример здесь тривиален, изменение каталога и создание файлов должно быть простым на любом языке программирования. Но даже если вам нужно запустить внешнюю команду, обычно нет необходимости делать это через оболочку.
Так, например, в Python вместо запуска
os.system("somecmd " + somearg)
используйтеsubprocess.run(["somecmd", somearg])
. В C вместоsystem()
, используйтеfork()
иexec()
(или найдите библиотеку, которая делает это).Если вам нужно использовать оболочку, процитируйте аргументы командной строки или передайте их через окружение, как в ответе Стефана . Кроме того, если вы беспокоитесь о специальных символах, правильное решение состоит в том, чтобы не пытаться отфильтровывать (черный список) потенциально опасных символов, а только сохранять символы, о которых известно, что они безопасны (белый список).
Разрешите только персонажам, чьи функции вы знаете, таким образом, существует меньший риск что-то упустить. Конечным результатом может быть то, что вы только решите разрешить
[a-zA-Z0-9_]
, но этого может быть достаточно для выполнения работы. Возможно, вы также захотите убедиться, что ваш язык и набор инструментов не включают в себя буквы с акцентом, какä
иö
в этом. Они, вероятно, не считаются специальными в какой-либо оболочке, но, опять же, лучше быть уверенным, пройдут они или нет.источник
[a-zA-Z0-9]
, не включает в себя такие вещи, какà
кодировка которых также может быть неверно истолкована некоторыми оболочками (напримерbash
) в некоторых локалях.В языке программирования должны быть более эффективные способы, чем выполнение команд оболочки. Например, замена
cd var
эквивалентом языка программированияchdir (var);
должна гарантировать, что любой обман со значениемvar
only приводит к ошибке «Directory not found», а не к непреднамеренным и, возможно, вредоносным действиям.Кроме того, вы можете использовать абсолютные пути, а не изменять каталоги. Просто объедините имя каталога, косую черту и имя файла, который вы хотите использовать.
В C я мог бы сделать что-то вроде:
Конечно, ваш язык программирования может сделать что-то подобное?
источник