Вызывает ли система() зло?
Я разрабатываю приложение на С++, которое, между прочим, время от времени выполняет несколько скриптов. Приложение должно быть эффективным и предпочтительно независимым от платформы.
Проблема заключается, однако: есть ли причина, по которой нельзя использовать вызов system()
для запуска сценариев и использовать, например, объекты POSIX? Обсуждение вопроса, которое я видел до сих пор, обычно сводится к следующему:
-
system()
менее гибкий. (Хорошо со мной)
- Он не контролирует выполняемую команду. (Хорошо со мной, мне просто нужно вернуть значение из script)
- Это не совсем независимая от платформы. (Теперь это будет проблемой. Мне бы очень хотелось увидеть пример, где он ведет себя по-разному на разных платформах).
- Это проблема безопасности. (Опять же, это будет проблемой. Может ли кто-нибудь представить пример потенциальной проблемы безопасности с
system()
?)
- Любые другие проблемы?
Ответы
Ответ 1
(3) Если вам нужен только контрпример, например, grep ведет себя по-разному в Solaris vs Linux vs whatever.
(4) Ваши программные привилегии унаследованы его порожденными программами. Если ваше приложение когда-либо работает как привилегированный пользователь, все, что ему нужно сделать, это поместить свою собственную программу с именем того, что вы выкладываете, а затем может выполнять произвольный код (это означает, что вы никогда не должны запускать программу, которая использует system
как root или setuid root).
(5) Вероятно, будет разумно поддерживать в конечном итоге использование средств posix, потому что вам не придется полагаться на определенный набор внешних скриптов или исполняемых файлов, которые уже существуют везде, где ваша программа работает.
Ответ 2
3) Он не совсем независим от платформы (теперь это будет проблемой. Мне очень хотелось бы увидеть пример, где он ведет себя по-разному на разных платформах)
Ну, например, system("ls")
, вероятно, завершится с ошибкой в Windows, так как не существует команды ls.
4) Это проблема безопасности. (Опять же, это будет проблемой. Может ли кто-нибудь представить пример потенциальной проблемы безопасности с системой()?)
Если аргумент, переданный в system
, поступает из пользовательского ввода и не проверяется корректно, его можно использовать для выполнения нежелательных действий с уровнями привилегий исходного исполнятеля. Если его статический контент, его довольно легко найти, что внутри исполняемого образа и изменить его, чтобы делать неприятные вещи, а также.
Ответ 3
Я поддерживаю систему, состоящую из нескольких отдельных исполняемых файлов. В этом случае я контролирую разрешения, имена, соглашения о вызовах, безопасность на всех поддерживаемых платформах. В этом случае система() работает просто отлично. Приложения взаимодействуют через СУБД.
Опять же, как другие отметили "Дьявол в деталях".
Ответ 4
Что касается соображений безопасности, классический пример (4) - это следующий сценарий: представьте, что пользователю предлагается предоставить некоторое имя каталога для резервного копирования в std::string dirname
; то вы вычислите некоторое имя каталога резервного копирования в std::string backup
и выполните
system((std::string{"cp -a "} + dirname + " " + backup).c_str())
Теперь подумайте, что произойдет, если злоумышленник вводит foo bar; rm -rf $HOME; ls
в качестве dirname
и backup
is /vol/backup_2015_fev/
. Команда system
выполнила бы
cp -a foo bar; rm -rf $HOME; ls /vol/backup_2015_fev/
который не является тем, что вы ожидали (все пользователи $HOME
будут удалены!). Это пример инъекции кода, и при использовании system
вы должны убедиться, что это никогда не происходит (например, путем дезинфекции и/или избежания каждого пользователя входная строка)
Кроме того, PATH
может быть не тем, чем вы считаете (например, начиная с /tmp/
и злонамеренного пользователя, выполнившего ln -s /bin/rm /tmp/cp
до запуска system
).
Ответ 5
Я использовал вызов system() в моем приложении CGI С++ под окнами и Linux.
Одна из проблем, с которыми я столкнулась, заключалась в том, что при использовании системы() не было прав доступа для выполнения моего skript с веб-пользователем.
У меня не было этой проблемы при использовании метода CreateProcess().