首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >缓冲区溢出漏洞

缓冲区溢出漏洞
EN

Stack Overflow用户
提问于 2016-02-22 06:09:29
回答 3查看 1.2K关注 0票数 1

以下节目:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 int check_authentication(char *password) 
{
 int auth_flag = 0;
 char password_buffer[16];
 strcpy(password_buffer, password);
 if(strcmp(password_buffer, "unipi") == 0)
    auth_flag = 1;
 if(strcmp(password_buffer, "SSL") == 0)
    auth_flag = 1;
 return auth_flag;
}

int main(int argc, char *argv[]) {
 if(argc < 2) {
    printf("Usage: %s <password>\n", argv[0]);
    exit(0);
 }
 if(check_authentication(argv[1])!=0)
 {
    printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
    printf(" Access Granted.\n");
    printf("-=-=-=-=-=-=-=-=-=-=-=-=-=-\n");
 }
 else
 {
     printf("\nAccess Denied.\n");
 }
}

strcpy(password_buffer, password);行,它存在缓冲区溢出漏洞。如果我们想在不取出strcpy的情况下使这个程序安全,它怎么可能?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-02-22 12:12:14

很简单。您可以更改用户输入是否与预期相同的验证。使用strlen,以便您可以检查字符串是否小于16个字节。

代码语言:javascript
复制
if(strlen(argv[1]) > 15)
{
    printf("too long password\n");
    exit(0);
}
票数 2
EN

Stack Overflow用户

发布于 2016-02-22 11:36:50

我在Wiki上发现了这个:

为了防止缓冲区溢出在本例中发生,可以将对strcpy的调用替换为strncpy,它以A的最大容量作为附加参数,并确保向A写入的数据量不超过此数量: strncpy(password_buffer,密码,大小(A)); 请注意,上面的代码也没有问题;虽然这次防止了缓冲区溢出,但如果源字符串的长度大于或等于缓冲区的大小(传递给函数的第三个参数),则strncpy库函数不会为空-终止目标缓冲区,因此在这种情况下,A不是以空结尾的,不能被视为有效的C样式字符串。

票数 1
EN

Stack Overflow用户

发布于 2016-02-22 18:49:12

有几种方法可以解决这个问题。

首先,也许最重要的一点是,避免了固定内存分配(),特别是在处理输入时。在上面的示例中,您可以将缓冲区设置为所需大小,而不是复制到固定大小的缓冲区。

代码语言:javascript
复制
char password_copy[strlen(password) + 1];
strcpy(password_copy, password);

但这并不总是可能的。也许你已经分配了内存。也许您确实希望截断输入(尽管是对于密码来说,16太小了)。

一是根本不使用C字符串处理函数,它们充斥着漏洞和安全漏洞。相反,可以使用像Gnome这样的库,它的功能是字符串类型。G_Strings跟踪它们的长度和分配的大小。这需要更多的记忆,但速度更快。查找字符串的长度,这是经常发生的事情,并不需要遍历字符串的每个字节。

字符串有自己的一组字符串处理函数。,它比C语言要简单得多。它还可以根据需要增长字符串或为您分配新字符串。

代码语言:javascript
复制
/* Allocate memory for the copy and copy the password */
G_String *password_copy = g_string_new(password);

为了与常规字符串函数兼容,password_copy->str返回一个正常的char *

这是我最好的方法。您不再需要记住检查字符串的长度和分配的大小,并担心在任何地方使用字符串都会出现空字节。你会忘记的。让电脑来做吧。

如果必须使用C标准函数,请不要使用strncpy,因为它无法保证截断字符串将为空终止。相反,请使用strlcpy。它类似于strncpy,但它保证复制的字符串将为null。strlcpy是一个BSD扩展,所以不能保证它是可移植的。glibc拒绝执行它。

为了最大限度地提高可移植性、效率和安全性,请使用strlcpy,并使用memmove#ifndef strlcpy提供退路,因此只有在strlcpy尚未可用时才会使用。

代码语言:javascript
复制
#include <string.h>
#include <stdio.h>

#ifndef strlcpy
size_t strlcpy(char * restrict dst, const char * restrict src, size_t dst_size) {
    /* size is the allocated size. len leaves space for the null byte */
    size_t dst_len = dst_size - 1;
    size_t src_len = strlen(src);

    /* Use the smaller of the two string lengths to avoid buffer overflow */
    size_t move_len = src_len > dst_len ? dst_len : src_len;

    /* Copy the string, truncate if necessary. It will work
     * even if src and dst overlap. */
    memmove(dst, src, move_len);

    /* Guarantee there's a null byte */
    dst[move_len] = '\0';

    /* strlcpy returns the size of the string it tried to make.
     * This is used to detect truncation. */
    return src_len;
}
#endif

int main()
{
    char dst[10];
    char *src = "12345678901234567890";

    printf("%zu\n", strlcpy(dst, src, 10));
    printf("src: %s, dst: %s\n", src, dst);

    return 0;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35560270

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档