格式化字符串漏洞
Posted ch42e
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了格式化字符串漏洞相关的知识,希望对你有一定的参考价值。
概述
格式化字符串漏洞最早是在1999年被Tymm Twillman发现的,他在著名的BugTrag邮件列表中公布了一篇关于proftpd软件漏洞的文章Exploit for proftpd 1.2.0pre6,这就是最早关于格式化字符串漏洞的公开描述。
由于程序使用了格式化字符串作为参数,并且格式化字符串是用户可以控制的。触发格式化字符串漏洞的主要函数就是printf、sprintf、fprint、vprintf
等ptintf
家族函数。恶意用户可以使用%s
和%x
等格式符,从堆栈或其他内存位置输出数据,也可以使用%n
向任意地址写入被格式化的字节数,可能造成任意代码的执行,或者从漏洞程序中读取铭感信息。
以printf
为例:
printf("<式样化字符串>",<参数表>);
函数printf
从右到左压栈,然后将先读取放到栈底,最后读取的放在栈顶,处理时候是从栈顶开始的,所以我们看见的结果是,从右边开始处理的。
printf("Number %d has no address,number %d has:%08x
",i,a,&a);
栈顶
+--------+
| ... |
| &a |
| a |
| i |
| A |
| ... |
+--------+
栈底
其中A
是格式化字符串的地址,i
是变量i
的值,a
是变量a
的值,&a
是变量a
的地址
一些格式化参数
格式化字符串%n
功能:将%n之前打印出来的字符个数,赋值给一个变量
如上所示,在%n
之前打印了5个字符a,所以最后n
的值为5;
格式化字符串%s
任意的内存的读取需要用到格式化字符串 %s,其对应的参量是一个指向字符串首地址的指针,作用是输出这个字符串
格式化字符串%x
漏洞成因
先看下面这段代码:
#include<stdio.h>
int main(){
char str[100];
scanf("%s",&str);
printf("%s",str);
printf(str); //触发漏洞
return 0;
}
针对于上面的列子,第一个printf
的调用时正确的,第二个printf
的调用是错误的。
漏洞形成原因:程序将格式化字符串的输入权交给用户,printf
函数并不知道参数个数,它的内部有个指针,用来索检格式化字符串。对于特定类型%
,就去取相应参数的值,直到索检到格式化字符串结束。所以没有参数,代码也会将format string
后面的内存当做参数以16进制输出。这样就会造成内存泄露。
对于上面的例子,输入:
aaaa%x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x,%08x
程序输出:
aaaabfe582ec,b7f6f950,004b61c0,00000000,00c30000,00000001,61616161,252c7825,2c783830,78383025,3830252cr
参考
(1)https://www.freebuf.com/column/207425.html
(2)https://blog.csdn.net/qq_43394612/article/details/84900668
(3)《漏洞战争——软件漏洞分析精要》
(4)《0day安全:软件漏洞分析技术》
拓展阅读
https://bbs.ichunqiu.com/thread-42943-1-1.html?from=bkyl
以上是关于格式化字符串漏洞的主要内容,如果未能解决你的问题,请参考以下文章
Format String Vulnerability Lab(格式化字符串漏洞实验最新版——2020年1月12日更新)