1

为什么此代码不安全?

#include <stdio.h>
int main( int argc, char *argv[] )
    {
       printf(argv[1]);
       printf("\n");
       return 0;
    }
4

5 回答 5

5

printf将处理它的第一个参数,寻找类似%dand的东西%s

基于这些值,它将从堆栈中获取更多数据并将其打印出来。

因此,如果有人调用您的程序:

a.out "%d %d %d %d %d %d %d %d %d %d %d %d"

他们可以查看您计算机调用堆栈的一部分。

如果他们对格式说明符更有创意,也许他们可以转储一些重要的东西,比如信用卡号或密码。

于 2012-04-09T21:15:33.270 回答
4

考虑printf控件的第一个参数是什么(提示:printf不只是读取它的输入参数)。

于 2012-04-09T21:13:04.323 回答
4

看看什么是格式字符串漏洞:

http://en.wikipedia.org/wiki/Uncontrolled_format_string

于 2012-04-09T21:14:07.330 回答
1

由于海报询问了一个例子,它做了什么%n

printf格式字符串可以改变内存的方式是使用%n选项;可以通过“明智地”使用格式宽度说明符来获得要写入的特定值。作为测试:

#include <stdio.h>

int main(int argc, char **argv)
{
    int *q = (int *)argv[0];
    printf("%1$300000d%5$n",
        123,         // %1 - 1st param (formatted as '300000d')
        0,           // %2 - 2nd param (unused)
        0,           // %3 - 3rd param (unused)
        0,           // %4 - 4th param (unused)
        argv[0]);    // %5 - 5th param (written to via 'n')

    printf("\nNow *q == %d\n", *q);

    return 0;
}

如果您运行它并查看输出的最后一行,它将打印Now *q == 300000(在 Linux 上测试)。

我在这里使用了相当未知的位置格式语法%<pos> $<fmt>),printf()以展示如何跳过参数来选择要修改的参数,而无需使用任何“无趣”的参数。

我将把它留给读者进行实验,以找出printf()printf(argv[1]). 答案取决于调用约定(或相关的,您系统的ABI),并且对于 32/64 位 Windows/Linux/MacOSX 等不同。

于 2012-04-12T10:43:29.987 回答
1

你可以在这里找到解释。 https://www.owasp.org/index.php/Testing_for_Format_String

于 2012-04-09T21:16:13.263 回答