C - 使用环境变量安全执行system()或exec()

时间:2014-06-19 19:36:20

标签: c linux

我有两个字符串,两个字符串都可以由用户设置,例如

char *command = "vim $VAR";
char *myVar = "/tmp/something";

我想使用*command *myVar执行$VAR

我尝试将它们连接为环境变量(例如(伪代码)system("VAR=" + *myVar + "; " + *command),但是用户控制myVar因此这将是非常不安全和错误。

我考虑过对空格进行标记以直接替换$var并将结果传递给exec(),但是担心正确地标记shell命令参数会让人感到尴尬。

我认为解决方案是通过执行类似system()的操作来模拟exec("sh", "-c", command, "--argument", "VAR", myVar),但我无法在sh / dash / bash手册页中看到任何内容以允许设置环境变量就这样。

编辑:我刚看到execvpe(),它有一个参数用于设置key = value字符串的环境变量。使用不受信任的输入值是否安全?

我该如何安全地做到这一点?

4 个答案:

答案 0 :(得分:2)

您需要引用myVar中包含的字符串;这可能意味着逃避顽皮的角色(例如反斜杠)。

您可以使用 Glib

中的g_shell_quote

答案 1 :(得分:2)

正如Ben指出的那样,command可能在运行时加载。

我认为最好的方法是标记command,而不是标记myVar。然后,您可以找到command中的哪个词$VAR,并将其替换为myVar的值。然后,您可以按照以下方式使用posix_spawnp

如果您真的希望command成为任意shell命令,那么您唯一的选择是在将myVar分配给环境变量之前将其转义。否则shell将扩展空格和其他特殊字符,无论你如何设置它。

第三个选项是确保命令为vim "$VAR"而不是vim $VAR。在这种情况下,您可以使用setenv将其分配给环境,然后调用system,然后在之后取消设置。

案例command中的旧答案是静态的:

看起来你真正想做的是

extern char *environ[];
posix_spawnp(NULL, "vim", NULL, NULL, (char*[]){"vim", myVar, NULL}, environ);
wait(NULL);

即。 exec vim直接没有任何shell,myVar作为第一个参数。

答案 2 :(得分:2)

您可以对myVar的值执行一些字符串替换 - 将其放在单引号内,并用四个字符的字符串'替换所有单引号(字符'\'') 。如果你没有犯一个实现错误,那就很安全但很安全。如果可能,use a library that does it for you

如果你的程序是单线程的,我推荐一个不涉及繁琐引用的不同解决方案。你谈到设置环境变量......好吧,就这样做:make VAR一个环境变量。

setenv("VAR", myVar, 1);
system(command);
unsetenv("VAR")

我省略了错误检查,我认为程序中的其他地方不需要VAR(如果是,这个解决方案变得更加繁琐,因为你需要记住旧值)。

如果要对命令运行的环境进行精细控制,可以在systemfork(或execve)和{{execvpe之上重新实现waitpid。 1}},或posix_spawn(或posix_spawnp)和waitpid之上。这是更多的努力,但你获得了灵活性。

请注意,除了在C程序中对"vim $VAR"执行字符串替换之外,您采用的任何解决方案都必须是vim "$VAR"而不是vim $VAR。这是因为在shell语法中,$VAR仅表示“变量VAR的值”,只有当它在双引号内时 - 否则,$VAR表示“取VAR的值,将其拆分为单词,并将每个单词扩展为文件名通配符模式“。

答案 3 :(得分:-2)

怎么样:

  1. fork(如果模仿systemspawn,请跳过此操作exec
  2. 叉子中的
  3. setenv("VAR", myVar)
  4. exec" sh -c" +命令