[英]Find the vulnerability in the C program
学习软件安全考试并遇到此问题但找不到漏洞。 如果您输入姓名“John Doe”和薪水 4000,那么程序将写入字符串“John Doe: $4000”。 据我所知,程序占\0,没有格式字符串错误,没有缓冲区溢出。 不知道我错过了什么。
编辑:忘记添加“名称”参数可以假定为有效的以空字符结尾的字符串。
/* 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: $%u\n", name, salary);
// Write buffer to file
fputs(buffer, global_file_handle);
}
count_digits
错误地将零返回为零。 正确的结果是一。 工资为零的 251 个字符的名称将需要 257 个字符(名称为 251,工资为 1,颜色、空格、美元符号、换行符和 null 为 5),但len
将被错误地计算为 256,并且len > sizeof(buffer)
不会被触发,所以代码会溢出buffer
。
(另一个问题是当name
不是以 null 结尾时strlen
具有未定义的行为,但从问题陈述中并不清楚name
的上下文。)
这不是一个答案,而是一个示例代码可能应该避免 Erik Postpischil 描述的缓冲区溢出。
count_digits
function 是错误的(在0
的情况下),但也是不必要的。 可以使用snprintf
将 output 限制为buffer
:
void add_record(const char* name, unsigned int salary)
{
char buffer[256];
int len;
len = snprintf(buffer, sizeof buffer, "%s: $%u\n", name, salary);
if (len >= sizeof(buffer)) {
printf("Too long string");
exit(1);
}
fputs(buffer, global_file_handle);
}
请注意,如果len
正好等于sizeof buffer
,这将意味着生成的字符串已经被截断。 事实上, len + 1
是buffer
应该防止截断的大小。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.