Предположим, что ваша команда выглядит так:
def post_result(result_string):
os.system('curl http://example.com/report-result/%s' % (result_string,))
Теперь, что произойдет, если вам сообщают о результатах, которые содержат ; rm -rf ~
? Оболочка, вызванная os.system()
, запускает curl http://example.com/report-result/
, а затем выполняет вторую команду rm -rf ~
.
например:
# Adding double quotes should work, right?
# WRONG: ''; rm -rf ~'' doesn't work here, but $(rm -rf ~) still does.
os.system('curl http://example.com/report-result/"%s"' % (result_string,))
# ...so, how about single quotes?
# STILL WRONG: $(rm -rf ~) doesn't work on its own, but result_string="'$(rm -rf ~)'" does.
os.system("curl http://example.com/report-result/'%s'" % (result_string,))
Во время запуска оболочка выполняет ряд операций на основе содержимого файловой системы и переменных среды. Если ненадежный пользователь может манипулировать вашей программой в настройке переменных окружения по своему выбору до вызова os.system()
, они могут заставить файл с именем в ENV
выполнить свои команды; может теневые команды с экспортированными функциями или может вызвать другие озорства. См. ShellShock для хорошо опубликованного исторического примера.
И прежде чем рассматривать другие вещи, которые могут случиться с вашими данными. Если вы передаете имя файла в оболочку, но неизвестно вам, оно содержит символы пробелов и glob, это имя файла может быть разделено на / заменено другими именами.
Цитирование предупреждения из документации модуля Python subprocess
, что также актуально здесь:
Предупреждение: выполнение команд оболочки которые включают неанитированный ввод из ненадежного источника, делают программу уязвимой для инъекции оболочки, серьезную проблему безопасности, которая может привести к произвольному выполнению команды. По этой причине использование
shell=True
сильно не рекомендуется в случаях, когда командная строка построена из внешнего ввода:>>> from subprocess import call >>> filename = input("What file would you like to display?\n") What file would you like to display? non_existent; rm -rf / # >>> call("cat " + filename, shell=True) # Uh-oh. This will end badly...
shell=False
отключает все функции на основе оболочки, но не страдает от этого уязвимость; см. примечание в документации конструктораPopen
для полезных подсказок при работеshell=False
.При использовании
shell=True
,pipes.quote()
можно использовать для правильного удаления пробелов и метасимволов оболочки в строках, которые будут использоваться для создания команд оболочки.
os.system()
имеет все те же ошибки, что иsubprocess.Popen(..., shell=True)
- даже больше сбоев, посколькуsubprocess.Popen()
обеспечивает способ передачи данных вне диапазона из кода, и поэтому можно безопасно использовать .Исходные библиотеки Python не вызывают оболочки для работы, которые Python может работать.
Python имеет библиотеку
socket
в своем стандартном библиотечном интерфейсе, который непосредственно вызывает вызовы операционной системы и libc для создания сетевых подключений и взаимодействия с ними. В этих системных вызовах нет оболочки; аргументами являются C-структуры, строки C и т. д .; поэтому они не подвержены уязвимостям инъекции оболочки так же, какos.system()
.Некоторые библиотеки Python, такие как
libcurl
, могут быть немного менее родными, поскольку они используют свои собственные библиотеки C, а чем вызов только операционной системе через функции, входящие в состав самой Python; даже тогда эти системные системы на уровне OS находятся на гораздо более низком уровне, чем любая оболочка.
Полагаю, вы имеете в виду ListBox
, а не Combobox
, верно?
Так что я также предполагаю, что у вас уже есть код для чтения выбранных элементов вашего ListBox, например:
Dim item As Variant
For Each item In YourListBox.ItemsSelected
Debug.Print YourListBox.ItemData(item)
Next
По поводу вашей проблемы:
Вы писали, что поле таблиц Reference_ID
хранит само число, но, поскольку оно отформатировано как "R-"000
, оно отображает значения, подобные R-003
.
Итак, вы уже знаете, что само сохраненное значение не форматируется. Вы можете проверить это, извлекая данные следующим образом:
?DLookup("Reference_ID","References","Reference_ID = 3")
Это будет отображаться 3
, а не R-003
.
То же самое относится и к чтению данных из выбранных элементов ListBoxes.
Насколько я знаю, вы не можете прочитать форматированный текст из ListBox. Но вы можете самостоятельно отформатировать значение чтения:
Dim item As Variant
For Each item In YourListBox.ItemsSelected
Debug.Print Format(YourListBox.ItemData(item), "R-000")
Next
Другой подход может заключаться в том, чтобы установить для источника строки вашего ListBox уже отформатированные значения:
Select Format(Reference_ID, "R-000") From References