查找C程序中的漏洞

0 c security c-strings

在准备软件安全考试时遇到了这个问题,但找不到漏洞。如果您输入姓名“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);
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*hil 5

count_digits错误地以零返回零。正确结果是一。工资为零的 251 个字符的姓名将需要 257 个字符(姓名 251 个,工资 1 个,颜色、空格、美元符号、换行符和空 5 个),但会被错误地len计算为 256,并且len > sizeof(buffer)将不会被触发,所以代码会溢出buffer

(另一个问题是strlen当不是以 null 终止时具有未定义的行为,但从问题陈述中不清楚 的name上下文。)name

  • @Jabberwocky:如上所述,上下文尚不清楚。此例程可以在某种程度上防止传递非空终止的字符串,并且这可能是例程的要求。公平地说,彻底做到这一点需要访问某种机制来检测未映射的内存。但漏洞分析超出了 C 标准所保证的范围。 (3认同)
  • 我会`#define BUFFER_SIZE (256)`,重写为`char buffer[BUFFER_SIZE];`,然后用`strnlen(<arg>,BUFFER_SIZE)`替换`strlen`...可能不是正确的方法但我发现这种方法有助于避免幻数问题。 (2认同)