格式字符串是包含文本和格式参数的ASCII字符串。
例子:
// A statement with format string printf("my name is : %s", "Akash"); // Output // My name is : Akash
在C和许多其他编程语言中,有几种格式字符串指定输出,但我们的重点是C。
格式字符串漏洞是一类利用容易避免的程序员错误的漏洞。如果程序员将攻击者控制的缓冲区作为参数传递给printf(或任何相关函数,包括sprintf、fprintf等),攻击者可以对任意内存地址执行写操作。以下程序包含此类错误:
// A simple C program with format // string vulnerability #include<stdio.h> int main( int argc, char ** argv) { char buffer[100]; strncpy (buffer, argv[1], 100); // We are passing command line // argument to printf printf (buffer); return 0; } |
由于printf的参数数量可变,它必须使用格式字符串来确定参数的数量。在上述情况下,攻击者可以传递字符串“%p%p%p%p%p%p%p%p%p%p%p%p%p%p”并欺骗printf,使其认为它有15个参数。它会天真地在堆栈上打印接下来的15个地址,认为它们是它的参数:
$ ./a.out "%p %p %p %p %p %p %p %p %p %p %p %p %p %p %p" 0xffffdddd 0x64 0xf7ec1289 0xffffdbdf 0xffffdbde (nil) 0xffffdcc4 0xffffdc64 (nil) 0x25207025 0x70252070 0x20702520 0x25207025 0x70252070 0x20702520
在堆栈上大约10个参数处,我们可以看到0x252070的重复模式——这些是堆栈上的%ps!我们以AAAA开头的字符串可以更明确地看到这一点:
$ ./a.out "AAAA%p %p %p %p %p %p %p %p %p %p" AAAA0xffffdde8 0x64 0xf7ec1289 0xffffdbef 0xffffdbee (nil) 0xffffdcd4 0xffffdc74 (nil) 0x41414141
0x4141是AAAA的十六进制表示形式。现在我们有了一种方法,可以将任意值(在本例中,我们将0x4141)作为参数传递给printf。此时,我们将利用另一个格式字符串特性:在格式说明符中,我们还可以选择一个特定的参数。例如,printf(“%2$x”,1、2、3)将打印2。通常,我们可以使用printf(“%$x”)来选择printf的任意参数。在我们的例子中,我们看到0x4141是printf的第10个参数,因此我们可以简化string1:
$ ./a.out 'AAAA%10$p' AAAA0x41414141
防止格式字符串漏洞
- 始终将格式字符串指定为程序的一部分,而不是输入。大多数格式字符串漏洞都是通过将“%s”指定为格式字符串,而不是将数据字符串用作格式字符串来解决的
- 如果可能,将格式字符串设置为常量。提取所有变量部分作为调用的其他参数。有些国际化库很难使用
- 如果上述两种做法不可行,请使用以下防御措施: 格式保护 .在设计阶段很少见。也许是一种继续使用遗留应用程序并降低成本的方法。增加对第三方应用程序安全性的信任
工具书类 https://www.owasp.org/index.php/Format_string_attack https://www.exploit-db.com/docs/28476.pdf
本文由 阿卡什·沙兰 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。