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、filenameパラメーターを呼び出すだけです。

このファイル名をエスケープしようとしている場合、それはおそらく信頼できないソースからのものであることを意味します。

それを考えると、いくつかのポイント:

  • 苦労してファイル名をエスケープするのではなく、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 に答える