0
#define BUFSIZE 256

int escape_single_quotes(char *to, char *from, int max)
{  int l= 0;

  for (;*from;from++)
  {
    switch (*from)    {
      case '\'':
        if (l>=max-4) return 0; // not enough space for escaped chars!
// replace ' with '\''
        *(to++)= '\'';       
        *(to++)= '\\';
        *(to++)= '\'';
        l += 3;
      default:
        if (l>=max-1) return 0; // not enough space for this char!       
        *(to++)= *from;
        l++;
    }
  }
   *to= 0;

  return 1;
}
 int main(int argc, char *argv[])
{
  FILE *fp;
  char buf[BUFSIZE];
  char escaped_name[BUFSIZE];  char *filename;
  int lines, chars, cpl;


   if (argc != 2)
  {
    fprintf(stderr, "Usage: %s filename\n", argv[0]);
    exit(EXIT_FAILURE);
  }  
  filename= argv[1];
  printf("Counting %s ... \n", filename);

  if (!escape_single_quotes(escaped_name, filename, BUFSIZE))  {
    fprintf(stderr, "Escaped filename is too long!\n");
    exit(EXIT_FAILURE);
  }
   if (snprintf(buf, BUFSIZE, "wc -l '%s'", escaped_name)>=BUFSIZE)
  {
    fprintf(stderr, "Filename %s is too long!\n", filename);
    exit(EXIT_FAILURE);
  } 
  fp= popen(buf, "r");}

这个脚本对命令注入安全吗?它将'替换为'\''。有没有办法打破单引号并注入命令?

4

1 回答 1

1

如果我正确阅读了这个程序,它只会调用wc -l它的文件名参数。

当您尝试转义此文件名时,这可能意味着它来自您无法信任的来源。

鉴于此,几点:

  • 您可以使用 call 简单地检查这样的文件名是否存在,而不是痛苦地转义文件名,如果存在access(),您可以将其传递给 wc 而无需太多关注。
  • 即使是调用这个程序的人,我也不会信任,这意味着您不能信任自己的 PATH。换句话说,当你调用 时wc -l,你可能会说某事是邪恶的,因为有人做了以下事情:

    cp evilwc /tmp/wc
    export PATH=/tmp:$PATH
    ./yourprogram goodfilename
    

哎呀!即使文件名是好的,攻击者仍然能够欺骗您的程序调用恶意代码。

解决方案:

在这种特殊情况下,您可能可以wc -l自己实现而不调用任何外部 - 毕竟这是非常简单的算法。

此外,在调用外部程序时,您应该尝试使用全名来调用它们,例如/usr/bin/wc.

如果参数是文件名,最好在传递它们之前检查它们是否真的存在。

可能希望为有效字符清理参数,但这很容易出错,例如删除对所有非英语世界至关重要的非 ASCII 符号。

于 2013-01-07T07:40:10.417 回答