为什么这个代码是可被利用的?

问题描述:

为什么这段代码是不安全的?为什么这个代码是可被利用的?

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

为什么我们应该为您做作业? – 2012-04-09 21:12:42

+3

http://en.wikipedia.org/wiki/Uncontrolled_format_string – 2012-04-09 21:13:04

printf将处理它的第一个参数,寻找的东西像%d%s

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

所以,如果有人叫你的程序:

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

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

如果他们对格式说明符有更多的创造性,他们可能会转储一些重要的东西,比如信用卡号码或密码。

+1

用'%n'你甚至可以在内存中的任何地方写入 – ouah 2012-04-09 21:16:13

+0

是的,我认为它只打印%,因为它打印了argv [1],就是这样。 – 0x90 2012-04-09 21:17:58

+0

这是比较温和的; '%n'会导致主动损坏(例如修改控制流)。 – 2012-04-09 21:18:24

考虑一下的printf控制的第一个参数(提示:printf不只是读它的输入参数)。

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

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

由于海报问一个例子是什么呢%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上测试)。

我使用printf()这里的,而未知位置格式的语法% <POS> $ <FMT>),以显示如何能够跳过参数选择修改哪一个,而无需使用任何的“无趣”的。

我会让读者进行实验来找出printf()作为printf(argv[1])这样的调用的“参数”。答案取决于您的系统的calling conventions(或相关,ABI),并且对于32/64位Windows/Linux/MacOSX等不同。