以编程方式安全地执行 shell 命令

Executing shell command programmatically safely

可以通过调用执行 shell 命令的 system 函数来执行 shell 命令。

这显然不安全,因为有人可以滥用该程序并执行攻击者特定的 os 命令。

man page of system suggests using the exec(3)函数:

Do not use system() from a privileged program (a set-user-ID or set-group-ID program, or a program with capabilities) because strange values for some environment variables might be used to subvert system integrity. For example, PATH could be manipulated so that an arbitrary program is executed with privilege. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3) (which also use the PATH environment variable to search for an executable).

虽然我不是很明白其中的区别。是的,权限可能会有所不同,但我们仍在执行 os 命令并且它仍然容易受到攻击,不是吗?我错过了什么吗?

如何安全地执行系统命令而不担心它会被滥用?

we still executing os commands and it is still vulnerable, isn't it ?

设想以下 C 程序(为清楚起见,忽略所需的 C 错误处理):

char file[20];
fgets(file, sizeof(file), stdin);
file[strcspn(file, "\n")] = 0; // 
char cmd[200];
snprintf(cmd, sizeof(cmd), "touch %s", file);
system(cmd);

很好 - 一个创建文件的简单程序。但是现在我 运行 程序并输入:

file; sudo rm -r /

所以会发生的是 file="file; sudo rm -r /" 然后 cmd="touch file; sudo rm -r /" 结果 system 命令 运行s touch file 然后 运行 s sudo rm -r / 删除所有文件并造成灾难性损坏。

对比:

execl("touch", "touch", file, NULL);

将始终只是 运行 touch(在当前目录中)并且 touch 将仅尝试访问名为的目录(因为尾随 /)字面上 file; sudo rm -rf /。 (但是 PATH 可以被操纵并且 touch 可执行文件可以被替换,这就是为什么使用 execv 而不是 execl - 你的引述说明了这一点)。