Вызывает ли система() зло?

Я разрабатываю приложение на С++, которое, между прочим, время от времени выполняет несколько скриптов. Приложение должно быть эффективным и предпочтительно независимым от платформы.

Проблема заключается, однако: есть ли причина, по которой нельзя использовать вызов 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().