-1

CGI 用に C で ping スクリプトを作成しました。

意図したとおりに機能していますが、ユーザー入力を当然のことと考えているため、安全ではないと確信しています。コマンドをつなぎ合わせて認識されるようにする方法があるかどうかわかりませんか?

誰かが私のスクリプトを悪用する方法と、それを修正する方法を知っていますか?

ping スクリプト ソース

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
  printf("Content-Type: text/plain;charset=us-ascii\n\n");

  FILE* in = NULL;

  char buffer[100][100] = {};
  char server[100] = {};
  char concat_str[100] = {};

  char* ping = "ping ";
  char* option = " -c 4";

  int print_counter = 0;
  int read_counter = 0;

  char* query;
  query = getenv("QUERY_STRING");
  if(query == NULL)
    printf("ERROR\n");
  else
    sscanf(query,"server=%s", server);

  strcat(concat_str, ping);
  strcat(concat_str, server);
  strcat(concat_str, option);

  in = popen(concat_str, "r");
  if(in == NULL)
  {
    printf("ERROR\n");
    exit(1);
  }

  while(fgets(buffer[read_counter], 99, in) != NULL)
  {
    read_counter++;
  }

  pclose(in);

  if(read_counter != 9)
  {
    printf("ERROR\n");
    exit(1);
  }

  while(print_counter < (read_counter + 1))
  {
    printf("%s", buffer[print_counter]);
    print_counter++;
  }

  return 0;
}

htmlソース

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>
</head>

<body>
<form action="http://xx.xx.xx.xx/ping.cgi">
<div><label>Server<input name="server" size="40"></label></div>
<div><input type="submit" value="start test"></div>
</form>

</body>
</html>

関連するメモとして、手動で 4 つのスペースを意図せずにソース コードをここに直接投稿する簡単な方法はありますか?

4

2 に答える 2

4
  1. すべての文字列リテラルは const である必要があります。例: const char *v = "value"、またはconst char v[] = "value"
  2. sscanfスタック オーバーフローが発生する可能性があります。最大で N 文字を読み取るように指示すると、安全になるはずです。例: sscanf(query,"server=%99s", server);.
  3. strcatバッファを完全に制御せずに呼び出すと、スタック オーバーフローが発生する可能性もあります。strncat代わりに使用してください。例: strncat(concat_str, option, sizeof(concat_str)-strlen(concat_str)-1).
  4. また、無期限にループして、配列while(fgets(buffer[read_counter], 99, in) != NULL)内の範囲外の位置にアクセスすることもできます。が有効な範囲内にあるbufferかどうかも確認する必要があります。read_counter0..99
于 2013-01-27T01:47:32.143 に答える
2

確かに安全ではありません。関数はそのpopen()引数をサブシェルに渡すため、シェルのメタ文字など;をクエリ文字列を介して渡して、任意のコマンドを実行できます。

于 2013-01-27T01:50:38.187 に答える