我刚用C语言为CGI写了一个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个空格?
答案 0 :(得分:4)
const char *v = "value"
或const char v[] = "value"
。sscanf
可能会导致堆栈溢出。告诉它最多读取N个字符,它应该是安全的。例如:sscanf(query,"server=%99s", server);
。strcat
也可能导致堆栈溢出。请改用strncat
。例如:strncat(concat_str, option, sizeof(concat_str)-strlen(concat_str)-1)
。while(fgets(buffer[read_counter], 99, in) != NULL)
也可能无限循环并访问buffer
数组中的越界位置。您还应该检查read_counter
是否在有效范围内0..99
。答案 1 :(得分:2)
绝对不安全。 popen()
函数将其参数传递给子shell,因此可以通过查询字符串传递像;
这样的shell元字符来执行任意命令。