【原理】浅析格式化串漏洞

浅析格式化串漏洞


创建时间:2001-03-03
文章属性:转载
文章来源:作者:isno (isno@sina.com)
文章提交: xundi (xundi_at_xfocus.org)

浅析格式化串漏洞

                       作者:isno (isno@sina.com)


                -----------------目录-------------------

                  一.前言

                  二.基础知识简介

                  三.格式化串漏洞原理

                    (1)参数个数不固定造成访问越界数据

                    (2)利用%n格式符写入跳转地址

                    (3)利用附加格式符控制跳转地址的值

                    (4)总结

                  四.对wu-ftp 6.0格式化串漏洞的分析

                    (1)问题出现在哪里

                    (2)wu-ftp漏洞的利用

                  五.后记

                ----------------------------------------

一.前言

    最近许多软件被发现存在格式化串漏洞,其中最著名的是wu-ftp6.0和rpc.statd,由于
相当多的网站缺省安装了这两种软件,而且网上针对这两个漏洞的攻击程序很多很好用,所
以由这两个漏洞而被攻破的网站非常之多。因此非常有必要认真研究一下格式化串漏洞,但
网上介绍格式化串漏洞的中文文章却特别少,就我知道的只有一篇warning3写的和另一篇
xuzq翻译的文章,我又参考了几篇英文文章,费了半天工夫看的头疼了才搞明白这种漏洞的
机理。

    由于那几篇文章写的较为深奥,像我这样的普通初学者看起来很费劲,我想就我的理解
写一篇浅显一点的文章,使其他像我一样的菜鸟免受头疼之苦,同时也把这篇文章作为备忘
材料,等我以后忘了再回过头来看看:-)由于本人水平有限,谬误之处再所难免,欢迎多多
指教。

二.基础知识简介

    在了解格式化串漏洞之前有必要复习一下关于堆栈的基础知识,网上介绍缓冲区溢出的
文章很多,其中大多都介绍了堆栈的知识,读者可以自行参考那些文章,我在这里只是简单
的介绍一下。

    一个程序的动态数据通过一块叫做堆栈的区域来存放。堆栈处于内存的高端,它有个特
性:后进先出。当程序中调用子函数时,计算机首先把参数依次压入堆栈,然后把指令寄存
器(EIP)中的内容做为返回地址(RET)压入堆栈,第三个压入堆栈的是基址寄存器(EBP),然后
把当前的栈顶指针(ESP)拷贝到EBP,做为新的基地址。最后把ESP减去一定的数值,用来为本
地变量留出一定空间。
    
    普通的缓冲区溢出就是利用了堆栈生长方向和数据存储方向相反的特点,用后存入的数
据覆盖先前压栈的数据,一般是覆盖返回地址,从而改变程序的流程,这样子函数返回时就跳到了
黑客指定的地址,就可以按照黑客意愿做任何事情了。
    
    格式化串漏洞和普通的缓冲溢出有相似之处,但又有所不同,它们都是利用了程序员的
疏忽大意来改变程序运行的正常流程。下面详细介绍格式化串漏洞的原理,最后对wu-ftp6.0
格式化串漏洞进行一下分析。

三.格式化串漏洞原理
    
    所谓格式化串,就是在*printf()系列函数中按照一定的格式对数据进行输出,可以输出
到标准输出,即printf(),也可以输出到文件句柄,字符串等,对应的函数有fprintf,sprintf,
snprintf,vprintf,vfprintf,vsprintf,vsnprintf等。能被黑客利用的地方也就出在这一系列
的*printf()函数中,可能有人会问:这些函数只是把数据输出了,怎么能造成安全隐患呢?
在正常情况下当然不会造成什么问题,但是*printf()系列函数有三条特殊的性质,这些特殊
性质如果被黑客结合起来利用,就会形成漏洞。

(注:以下测试环境为RedHat Linux 6.0)

#可以被黑客利用的*printf()系列函数的三个特性:

(1)参数个数不固定造成访问越界数据

    首先第一个可以被利用的性质是:*printf()系列函数的参数的个数是不固定的。拿printf()
函数举例来说,如果我们要依次输出3个整型数据和1个字符串,可以用以下程序:

#include
int main(void)
{
int i=1,j=2,k=3;
char buf[]="test";
printf("%s %d %d %d/n",buf,i,j,k);
return 0;
}

  这是正常的使用方法,程序会输出:

test 1 2 3

    这个printf()函数共有5个参数,第一个是格式化串"%s %d %d %d/n",第二个是字符串buf的
地址,%s对应buf,其后的三个%d分别对应i,j,k,这样就把数据输出了。但是如果我们减少printf()
函数的参数个数,写成这样:

printf("%s %d %d %d/n",buf,i,j);

    格式化输出符号仍然是4个,但对应的数据却只剩下3个了(buf,i,j)了,那么情况会怎样呢?
我们编译运行一下看看,这个程序输出:

test 1 2 1953719668

    我们可以清楚的看到,尽管没有给最后一个%d提供对应的数据,但是它还是输出了一个10位的
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值