C 如何删除字符串中对“有特殊含义”的标点符号;bash“;在;";

C 如何删除字符串中对“有特殊含义”的标点符号;bash“;在;";,c,linux,string,bash,shell,C,Linux,String,Bash,Shell,我正在linux系统上用C语言开发一个电子邮件客户端,bash帮助我实现了一些小技巧 C客户端获取一封电子邮件,并将字符串或数据重定向到与该数据或字符串行有其他关系的脚本 但问题是,有时从在线电子邮件帐户获取的“字符串行”具有特殊的标点符号,当将这些标点符号传输到shell脚本时,在大多数情况下脚本无法执行,而很少更改脚本原始任务的含义 这与SQL注入攻击非常相似 我相信这也会非常危险,想象一下,有人给你发了一封电子邮件,其中包含一些shell命令,可以擦除你的硬盘或类似的东西 现在,我经常遇到

我正在linux系统上用C语言开发一个电子邮件客户端,bash帮助我实现了一些小技巧

C客户端获取一封电子邮件,并将字符串或数据重定向到与该数据或字符串行有其他关系的脚本

但问题是,有时从在线电子邮件帐户获取的“字符串行”具有特殊的标点符号,当将这些标点符号传输到shell脚本时,在大多数情况下脚本无法执行,而很少更改脚本原始任务的含义

这与SQL注入攻击非常相似

我相信这也会非常危险,想象一下,有人给你发了一封电子邮件,其中包含一些shell命令,可以擦除你的硬盘或类似的东西

现在,我经常遇到的问题是,电子邮件的大多数“主题”和“发件人”标题字段都包含带引号的字符串,当将这些字符串传输到该脚本时,会导致以下错误:

sh: 1: cannot open myemail@gmail.com: No such file
sh: 3: Syntax error: Unterminated quoted string
这两个标题字段应通过管道传输,并在C中首先附加:

 char *Subject=getSubject();
 char *From=getFrom();
 char completeString[256];
 sprintf(completeString,"./MyShellScript.sh \"Subject: %s and From: %s\"",Subject,From);
 /* Then executed via the system call */
 system(completeString);
我认为问题在于我已经为字符串提供了引号,但是当“Subject”或“FROM”已经在引号中时,脚本就会给出上面显示的错误

基本上,shell脚本有一行字符串输入,如下所示:

someOtherProgram -w=/tmp/temp.txt "$1"

This line expects a String like this "Hello Subject" and not ""Hello Subject""

我该怎么办?

不要用不可信数据生成的字符串调用
系统(completeString)
。相反,使用
execv
-family调用将参数从调用带外传递:

pid_t pid = fork()
int status;
if (pid < 0) {                                                       /* the fork failed */
  exit(1);
} else if (pid > 0) {                       /* the fork succeeded, and we're the parent */
  /* wait for the child to exit and collect its status */
  waitpid(pid, &status, 0);
} else {                                     /* the fork succeeded, and we're the child */
  /*            replace ourselves (as the child process) with an instance of the script */
  /*     executable         argv[0]          argv[1]  argv[2] terminator                */
  execlp("./MyShellScript", "MyShellScript", Subject, From,   NULL);
}
这是安全的,因为扩展只在shell启动后执行:由
system()
启动的
sh-c
副本实际调用的代码是您(希望)审核为正确的常量字符串


请注意,由于环境变量会自动转换为shell变量,您甚至不需要在显式命令中传递
“$Subject”
“$From”
——如果将环境作为
MyShellScript
的文档化调用约定的一部分,它可以直接引用
“$Subject”
“$From”
并查看通过
setenv()

放置在环境中的值。不要使用由不可信数据生成的字符串调用
系统(completeString)
。相反,使用
execv
-family调用将参数从调用带外传递:

pid_t pid = fork()
int status;
if (pid < 0) {                                                       /* the fork failed */
  exit(1);
} else if (pid > 0) {                       /* the fork succeeded, and we're the parent */
  /* wait for the child to exit and collect its status */
  waitpid(pid, &status, 0);
} else {                                     /* the fork succeeded, and we're the child */
  /*            replace ourselves (as the child process) with an instance of the script */
  /*     executable         argv[0]          argv[1]  argv[2] terminator                */
  execlp("./MyShellScript", "MyShellScript", Subject, From,   NULL);
}
这是安全的,因为扩展只在shell启动后执行:由
system()
启动的
sh-c
副本实际调用的代码是您(希望)审核为正确的常量字符串


请注意,由于环境变量会自动转换为shell变量,您甚至不需要在显式命令中传递
“$Subject”
“$From”
——如果将环境作为
MyShellScript
的文档化调用约定的一部分,它可以直接引用
“$Subject”
“$From”
并通过
setenv()

查看环境中放置的值坦率地说,不要做任何类似的远程操作。将shell脚本替换为C代码,并扫描字符串中是否有100%不安全的字符。Bash是用C编写的。是什么让你认为Bash可以做一些在C中做不到的事情?@DavidSchwartz,“扫描字符串中是否有100%不安全的字符”--我强烈反对,使用这种方法:您不能总是合理地将您的输入域限制在这样一个小的白名单中,以便在可以将数据解析为代码的上下文中安全地传递数据,并且尝试这样做会使系统的灵活性降低(因为它们不必要地限制了它们的输入域)。远比简单地将数据从代码带外传递要好得多,这样它就永远不会被解析。这就是为什么SQL注入的答案是绑定变量。@DavidSchwartz,……现在,在有些地方,带内信号被嵌入到协议设计中(hello,HTML),您需要清理数据。但这是一个设计上的失败,没有进入这种情况下放在首位。(顺便说一句——最好避免对可执行文件使用扩展名,包括
.sh
;使用它们意味着当您用不同的语言重写某些内容时,您需要更改所有其他程序,而且它们还意味着可以使用
sh
启动某些内容,从而鼓励绕过用于启动脚本的实际shebangd/忽略)。坦率地说,不要做任何类似的事情。用C代码替换shell脚本,并扫描字符串中所有不100%安全的字符。Bash是用C编写的。是什么让你认为Bash可以做一些在C中做不到的事情?@DavidSchwartz,“扫描字符串中所有不100%安全的字符”--我强烈反对这种方法:你不能总是合理地将你的输入域限制在这样一个小的白名单上,以便在一个可以被解析为代码的上下文中安全地传递数据,而这样做的尝试会使系统的灵活性降低(因为他们不必要地限制了他们的输入域)。远比从代码中简单地将数据传递到带外要好得多,这样它就永远不会被解析。这就是为什么SQL注入的答案是绑定变量。@DavidSchwartz,…现在,有些地方带内信号被嵌入到协议设计中(hello,HTML),然后您需要清理数据。但首先,这是一个设计错误,无法进入这种情况。(顺便说一句,最好避免对可执行文件使用扩展,包括
.sh
;使用它们意味着您需要更改