以下节目:
#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的情况下使这个程序安全,它怎么可能?
发布于 2016-02-22 12:12:14
很简单。您可以更改用户输入是否与预期相同的验证。使用strlen,以便您可以检查字符串是否小于16个字节。
if(strlen(argv[1]) > 15)
{
printf("too long password\n");
exit(0);
}发布于 2016-02-22 11:36:50
我在Wiki上发现了这个:
为了防止缓冲区溢出在本例中发生,可以将对strcpy的调用替换为strncpy,它以A的最大容量作为附加参数,并确保向A写入的数据量不超过此数量: strncpy(password_buffer,密码,大小(A)); 请注意,上面的代码也没有问题;虽然这次防止了缓冲区溢出,但如果源字符串的长度大于或等于缓冲区的大小(传递给函数的第三个参数),则strncpy库函数不会为空-终止目标缓冲区,因此在这种情况下,A不是以空结尾的,不能被视为有效的C样式字符串。
发布于 2016-02-22 18:49:12
有几种方法可以解决这个问题。
首先,也许最重要的一点是,避免了固定内存分配(),特别是在处理输入时。在上面的示例中,您可以将缓冲区设置为所需大小,而不是复制到固定大小的缓冲区。
char password_copy[strlen(password) + 1];
strcpy(password_copy, password);但这并不总是可能的。也许你已经分配了内存。也许您确实希望截断输入(尽管是对于密码来说,16太小了)。
一是根本不使用C字符串处理函数,它们充斥着漏洞和安全漏洞。相反,可以使用像Gnome这样的库,它的功能是字符串类型。G_Strings跟踪它们的长度和分配的大小。这需要更多的记忆,但速度更快。查找字符串的长度,这是经常发生的事情,并不需要遍历字符串的每个字节。
字符串有自己的一组字符串处理函数。,它比C语言要简单得多。它还可以根据需要增长字符串或为您分配新字符串。
/* 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尚未可用时才会使用。
#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;
}https://stackoverflow.com/questions/35560270
复制相似问题