【问题标题】:Regarding security flaw in strcpy关于 strcpy 中的安全漏洞
【发布时间】:2014-02-04 22:43:36
【问题描述】:

通过导致缓冲区溢出,我们可以覆盖保存标志值0的内存,因此即使密码不正确也会破解密码..

这将如何在内部发生?有人可以详细解释一下..这实际上会在内存中发生吗?

#include<stdio.h>

int main(int argc, char *argv[])
{
int flag = 0;
char passwd[10];

memset(passwd,0,sizeof(passwd));

strcpy(passwd, argv[1]);

if(0 == strcmp("LinuxGeek", passwd))
{
    flag = 1;
}

if(flag)
{
    printf("\n Password cracked \n");
}
else
{
    printf("\n Incorrect passwd \n");

}
return 0;

}

【问题讨论】:

  • 不太相关:你不需要在 strcpy() 之前将 memset 设置为零。

标签: c strcpy


【解决方案1】:

C 中的局部变量通常分配在堆栈上。堆栈在内存中趋于向下增长,因此“flag”的存储空间将紧随为“passwd”分配的存储空间之后。

strcpy 不检查被复制的数据量是否不会溢出数据被复制到的缓冲区。所以,假设 argv[1] 正好是 11 个字符,这就是会发生的事情:

  • 前 10 个字符将进入 passwd
  • char 11 将进入 flag 存储的第一个字节
  • 终止的空字符将进入标志存储的第二个字节

因此,flag 将不为零。

具体行为因编译器而异 - 但这是一种典型情况。

使用 strncpy 来避免这种情况。

【讨论】:

    【解决方案2】:

    请记住,从理论上讲,如果存储在passwd 中的字符串溢出,它会调用未定义的行为并且结果是不可预测的。

    实际上,在许多将局部变量存储在堆栈中的现代平台上,如果您的编译器将flag 放置在高于passwd 缓冲区的位置,它可能会被strcpy 调用溢出。

    即您的堆栈可能如下所示:

    | ...        |
    +------------+
    | flag       |  / \
    +------------+   |
    | passwd[10] |   | increasing addresses
    | ...        |
    

    如果您向passwd 写入超过10 个字节,strcpy 只会覆盖flag

    请注意,行为因编译器和平台而异。此解释涵盖了常见系统上发生的情况,但知道理论上可能有一个不使用堆栈的平台,因此此解释不适用。

    【讨论】:

    • 所以,答案是..它可能会也可能不会..所以局部变量的存储依赖于编译器..我认为它们是按声明的方式存储的..
    • 是的,由编译器决定它们的放置位置。
    猜你喜欢
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    • 2017-11-24
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    相关资源
    最近更新 更多