堆溢出攻击

时间:2015-05-20 18:49:41

标签: c buffer-overflow

我正在学习堆溢出攻击,我的教科书提供了以下易受攻击的C代码:

/* record type to allocate on heap */
typedef struct chunk {
    char inp[64];            /* vulnerable input buffer */
    void (*process)(char *); /* pointer to function to process inp */
} chunk_t;

void showlen(char *buf)
{
    int len;
    len = strlen(buf);
    printf("buffer5 read %d chars\n", len);
}

int main(int argc, char *argv[])
{
    chunk_t *next;

    setbuf(stdin, NULL);
    next = malloc(sizeof(chunk_t));
    next->process = showlen;
    printf("Enter value: ");
    gets(next->inp);
    next->process(next->inp);
    printf("buffer5 done\n");
}

然而,教科书并没有解释如何修复此漏洞。如果有人能够解释漏洞以及修复它的方法那将是很好的。 (部分问题是我来自Java,而不是C)

4 个答案:

答案 0 :(得分:5)

代码使用gets,因其潜在的安全问题而臭名昭着:无法指定传递给它的缓冲区的长度,它只会继续读取stdin直到它遇到\nEOF。因此它可能会溢出你的缓冲区并写入其外部的内存,然后会发生坏事 - 它可能会崩溃,它可能继续运行,它可能会开始播放色情内容。

要解决此问题,您应该使用fgets代替。

答案 1 :(得分:5)

问题是gets()将继续读取缓冲区,直到它读取换行符或达到EOF。它不知道缓冲区的大小,因此它不知道它应该在达到其限制时停止。如果该行是64字节或更长,则它将超出缓冲区,并覆盖process。如果输入输入的用户知道这一点,他可以在64位键入正确的字符,用一个指向其他函数的指针替换函数指针,而这个函数指的是他想要进行程序调用。

修复方法是使用gets()以外的函数,因此您可以指定要读取的输入量的限制。而不是

gets(next->inp);

你可以使用:

fgets(next->inp, sizeof(next->inp), stdin);

fgets()的第二个参数告诉它将最多64个字节写入next->inp。因此它将从stdin读取最多63个字节(它需要允许空字符串终止符的一个字节)。

答案 2 :(得分:1)

您可以通过设置process的地址来填充超过64个字节的下一个字节。从而使人们可以插入任何希望的地址。地址可以是指向任何函数的指针。

要修复简单,请确保只将63个字节(一个用于null)读入数组inp - 使用fgets

答案 3 :(得分:0)

函数获取不限制来自stdin的文本量。如果超过63个字符来自stdin,则会出现溢出。 gets丢弃LF char,这将是一个[Enter]键,但它在末尾添加一个空字符,因此63个字符限制。

如果inp的值填充了64个非空字符,因为它可以直接访问,showlen函数将触发访问冲突,因为strlen将搜索超出inp的null-char来确定其大小。

使用fgets可以很好地解决第一个问题,但它也会添加一个LF char和null,因此可读文本的新限制为62.

对于第二个,只需注意inp上的内容。