2008-12-30 199 views
3

Windows系统中的“格式字符串漏洞”到底是什么,它是如何工作的,以及如何防范它?防止格式化字符串漏洞

+0

那么,知道如何攻击有助于了解如何防御/避免漏洞。这就是公开披露这些漏洞/漏洞的想法。 – PhiLho 2008-12-30 16:10:44

回答

2

在用户输入某些字符此伪代码被打印,像“你好”

string s=getUserInput(); 
write(s) 

即如预期工作。但由于写入可以格式化字符串,例如

int i=getUnits(); 
write("%02d units",i); 

输出:“03单位”。如果用户在第一个地方写了“%02d”,那么...因为堆栈中没有参数,其他的东西都会被提取。那是什么,如果这是一个问题,则取决于该计划。

一个简单的办法是将程序告诉输出字符串:

write("%s",s); 

或使用不尝试格式化字符串的另一种方法:

output(s); 

一个link到维基百科更多信息。

4

格式字符串攻击,在其最简单的,是这样的:

char buffer[128]; 
gets(buffer); 
printf(buffer); 

那里面有一个缓冲区溢出漏洞为好,但问题是这样的:你传递不受信任的数据(从用户)到printf(或它的一个表兄弟)使用该参数作为格式字符串。

也就是说:如果用户输入“%s”,就会产生信息泄露漏洞,因为printf会将用户输入视为格式字符串,并尝试在堆栈上打印下一个内容作为一个字符串。就好像你的代码是printf("%s");。由于您没有将任何其他参数传递给printf,它会显示任意的内容。

如果用户输入“%n”,则可能会发生特权攻击(至少拒绝服务攻击)的潜在提升,因为%n格式字符串会导致printf写入打印的字符数远离堆栈上的下一个位置。既然你没有给它一个放置这个值的地方,它会写入任意的地方。

这一切都很糟糕,并且是使用printf和堂兄弟时应该特别小心的一个原因。

你应该做的是这样的:

printf("%s", buffer); 

这意味着,用户在输入时从来没有像格式字符串处理,所以你从那个特定的攻击向量安全。

在Visual C++中,您可以使用__Format_string注释来告诉它验证参数为printf%n默认是不允许的。在GCC中,您可以使用__attribute__(__printf__)来做同样的事情。