#python-3.x #bash #shell #input #sanitization
Вопрос:
Я занят написанием скрипта Python3, который требует ввода данных пользователем, ввод используется в качестве параметров в командах, передаваемых в оболочку.
Сценарий предназначен только для использования доверенными внутренними пользователями, однако я бы предпочел иметь некоторые непредвиденные обстоятельства для обеспечения корректного выполнения команд.
Пример 1:
import subprocess user_input = '/tmp/file.txt' subprocess.Popen(['cat', user_input])
Это выведет содержимое ‘/tmp/file.txt’
Пример 2:
import subprocess user_input = '/tmp/file.txt amp;amp; rm -rf /' subprocess.Popen(['cat', user_input])
Результаты (как и ожидалось):
cat: /tmp/file.txt amp;amp; rm -rf /: No such file or directory
Является ли это приемлемым методом очистки входных данных? Есть ли что-нибудь еще, согласно лучшей практике, что я должен делать в дополнение к этому?
Комментарии:
1. Нет, не из досье. Ввод осуществляется через интерактивное меню в терминале. Я просто упростил свой вопрос. Переменная «user_input» просто представляет все, что пользователь предположительно ввел в приложение.
Ответ №1:
Подход, который вы выбрали,
import subprocess user_input = 'string' subprocess.Popen(['command', user_input])
довольно хорош, так как command
статичен и user_input
передается как один единственный аргумент command
. До тех пор, пока ты не сделаешь что-нибудь действительно глупое, например
subprocess.Popen(['bash', '-c', user_input])
ты должен быть в безопасности.
Для команд, требующих нескольких аргументов, я бы рекомендовал вам запросить несколько входных данных у пользователя, например, сделайте это
user_input1='file1.txt' user_input2='file2.txt' subprocess.Popen(['cp', user_input1, user_input2])
вместо этого
user_input="file1.txt file2.txt" subprocess.Popen(['cp'] user_input.split())
Если вы хотите еще больше повысить безопасность, вы можете:
- явно задано
shell=False
(чтобы вы никогда не выполняли команды оболочки; это уже текущее значение по умолчанию, но значения по умолчанию могут меняться со временем):subprocess.Popen(['command', user_input], shell=False)
- используйте абсолютные пути для
command
(для предотвращения внедрения вредоносных исполняемых файлов черезPATH
):subprocess.Popen(['/usr/bin/command', user_input])
- явно проинструктируйте команды, которые его поддерживают, чтобы остановить параметры синтаксического анализа, например
subprocess.Popen(['rm', '--', user_input1, user_input2])
- сделайте как можно больше изначально, например
cat /tmp/file.txt
, вместо этого можно было бы использовать несколько строк кода Python (что также повысило бы переносимость, если бы это было фактором).