查找C程序中的漏洞



正在学习软件安全考试,遇到了这个问题,但找不到漏洞。如果输入名称";John Doe";以及工资4000,则程序将写入字符串"0";约翰·多伊:4000美元;。根据我所能告诉程序的\0,没有格式字符串错误,没有缓冲区溢出。不知道我错过了什么。

编辑:忘记添加";name";参数可以假定为有效的以null结尾的字符串。

/* Calculates the number of letters (i.e. digits) that are needed to represent a decimal number as an ASCII string */
size_t count_digits(unsigned int number)
{
unsigned int left = number;
size_t n= 0;
while(left != 0) {
left = left / 10;
n++;
}
return n;
}
void add_record(const char* name, unsigned int salary)
{
char buffer[256];
size_t len = strlen(name);
size_t num_digits = count_digits(salary);
/* 5 extra bytes required for colon and space after name + dollar sign, endline and NULL-terminator */
if(len > SIZE_MAX - 5 || len + 5 > SIZE_MAX - num_digits) {
printf("integer overflow");
exit(1);
}
len = len + num_digits + 5;
if (len > sizeof(buffer)) {
printf("Too long string");
exit(1);
}
/* Output formatted string to buffer (in the format string, %s denotes a string, and %u denotes an unsigned int that is printed as a decimal number) */
sprintf(buffer, "%s: $%un", name, salary);
// Write buffer to file
fputs(buffer, global_file_handle);
}

count_digits错误地将零归零。正确的结果是一。251个字符的名称如果薪资为零,则需要257个字符(251个字符表示名称,1个字符表示薪资,5个字符表示颜色、空格、美元符号、新行和null(,但len将被错误地计算为256,并且len > sizeof(buffer)将不会被触发,因此代码将溢出buffer

(另一个问题是,当name不是null终止时,strlen有未定义的行为,但问题语句中name的上下文不清楚。(

这不是一个答案,而是Erik Postpischil描述的避免缓冲区溢出的代码可能应该是什么的示例。

count_digits函数是错误的(在0的情况下(,但也是不必要的。可以使用snprintf:将输出限制为buffer

void add_record(const char* name, unsigned int salary)
{
char buffer[256];
int len;
len = snprintf(buffer, sizeof buffer, "%s: $%un", name, salary);
if (len >= sizeof(buffer)) {
printf("Too long string");
exit(1);
}
fputs(buffer, global_file_handle);
}

请注意,如果len恰好等于sizeof buffer,这将意味着生成的字符串已经被截断。事实上,len + 1buffer为防止截断而应该具有的大小。

最新更新