如何在C ++中转义发送到'system'命令的变量?

时间:2011-12-16 19:34:59

标签: c++ linux escaping

This question讨论使用system命令并传递变量。这是一个例子:

string cmd("curl -b cookie.txt -d test=");
cmd += line;
cmd += "  http://example.com";
system(cmd.c_str());

其中一条评论提到,如果line被传递并包含foo & fire_nukes.exe & REM,那么很可能发生一些不好的事情。

PHP有一个很好的函数叫escape_shell_args,它可以用来转义传递给程序的参数。 C ++有办法做到吗?

5 个答案:

答案 0 :(得分:4)

最好的方法是不要使用system()。使用fork()exec()以及朋友。 这是一个例子:

#include <string>
#include <unistd.h>
#include <error.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <cstdlib>

int fork_curl(char *line)
{
    std::string linearg("line=");
    linearg += line;

    int pid = fork();
    if(pid != 0) {
        /* We're in the parent process, return the child's pid. */
        return pid;
    }
    /* Otherwise, we're in the child process, so let's exec curl. */

    execlp("curl", "-b", "cookie.txt", "-d", linearg.c_str());  
    /* exec is not supposed to return, so something
       must have gone wrong. */
    exit(100);
    /* Note: You should probably use an exit  status
       that doesn't collide with these used by curl, if possible. */
}

int main(int argc, char* argv[])
{
    int cpid = fork_curl("test");
    if(cpid == -1) {
        /* Failed to fork */
        error(1, errno, "Fork failed");
        return 1;
    }

    /* Optionally, wait for the child to exit and get
       the exit status. */
    int status;
    waitpid(cpid, &status, 0);
    if(! WIFEXITED(status)) {
        error(1, 0, "The child was killed or segfaulted or something\n");
    }

    status = WEXITSTATUS(status);
    /* Status now contains the exit status of the child process. */
}

答案 1 :(得分:4)

切勿将用户输入传递到system来电。如初。

你可以试图逃避你认为危险的所有角色,但你会弄错。

相反,从另一个方向继续:让用户提供定义的任何输入选择,然后执行switch并从头开始构建自己的系统调用

不可否认,当要调用的命令行应用程序的输入是自由形式时,这有点棘手,但是,这就是实际库的用途。 libcurl,有人吗?

答案 2 :(得分:0)

你可以试试execl ..

http://linux.about.com/library/cmd/blcmdl3_execvp.htm

#include <unistd.h> 

int execl(const char *path, const char *arg, ...); 

答案 3 :(得分:0)

请参阅列出所有syscalls的手册页(系统调用不是伪造shell的system(3)函数。)

详细了解system callslinux kernel以及operating systems的整体组织

回到你的问题,你可以引用shell(只需遵循shell转义规则来转换你的字符串;例如,用反斜杠作为前缀任何非字母字符)。

另请参阅forkexecve等的手册页

advanced linux programming和着名的Advanced Unix Programming

上阅读一本好书

在Linux发行版上使用大多数软件的自由。例如,您可以研究像sash这样的简单shell的源代码。

也许你只想使用卷曲。然后,最好的方法是代码libcurl(无需调用system(3)

尽情学习这一切!

答案 4 :(得分:0)

您可以使用环境变量将参数安全地传递给system(3)执行的命令。

setenv ("mypar1", "'$(rm -rf /)", 1);
setenv ("mypar2", "\"; rm -rf /", 1);
system ("echo mypar1=\"$mypar1\" mypar2=\"$mypar2\");

这些邪恶代码都不会执行,只需打印即可。