溢出漏洞怎么利用/php整数溢出漏洞-零开始渗透教程

溢出漏洞怎么利用/php整数溢出漏洞-零开始渗透教程

我发现上没有整数溢出漏洞的基础介绍,所以这篇文章通过分析我刚刚发现的UPX源代码中的整数溢出漏洞,介绍一下C/C++整数溢出漏洞的原理、触发和修复方法。这篇文章暂不涉及如何利用整数溢出达到远程代码执行,UPX的漏洞只是一个拒绝服务漏洞。

0×01 整数溢出原理

C/C++中的整数溢出基本原理非常简单,比如 char = 200 + 200;。最终的值是400 mod 256=144。这是因为C++对于无符号整数( char, int等)溢出的处理是取模,导致的结果是两个整数相加,反而结果更小。C++中有符号整数溢出是未定义行为。下文中所有提到整数溢出,都指的是无符号整数溢出。整数溢出的利用一般都是用它来导致缓冲区溢出,进而利用缓冲区溢出技巧来代码执行、泄露内存或拒绝服务。

我认为对于文件解析一类的程序要特别注意整数溢出问题,因为有很多文件格式,它们的文件头中包含了长度、偏移信息。攻击者通过构造畸形文件可以直接控制这些信息,尝试触发整数溢出或其他缓冲区溢出漏洞。所以在写代码时我们需要关注的点有:第一,将整数运算的结果作为缓冲区长度分配内存;第二,将整数运算的结果作为偏移量读取内存。

对于第一点,比如这段代码:

len = len1 + 0x40; char * = new char[len]; [0x10] = 'a';

如果len1是攻击者可控的值,那么这里就存在整数溢出问题。假设是32位程序,攻击者选取len1 = ,那么len1+40等于1,所以的长度为1。第三行,作者错误地假设了下标0×10一定会在分配的内存区间内,但实际上这里发生了越界写入。

对于第二点,看这段代码:

char [100]; char = (); // 攻击者可控 if (40 + < ()) { [] = 0; }

这里作者错误地假设了如果40 + 这个index没有越界,则这个index也没有越界。但是如果我们取=255。则40 + = 39,那么我们就将[255]这个越界地址写入了0。

0×02 分析UPX整数溢出漏洞

这个漏洞是我最近找出来的UPX开源项目的漏洞。因为最近研究UPX,随手在CVE数据库里搜索了一下有没有UPX的漏洞,结果还真有,CVE-2017-15056。漏洞报告在 。这是一个畸形文件导致内存越界读取漏洞,我看了一下修复的。从来看,修复并不完美,而且正好可以拿来讲整数溢出。

我们重点看中::函数中添加在250-256行的校验:

php整数溢出漏洞_整数溢出漏洞_溢出漏洞怎么利用

是用户输入的ELF文件的大小,, , , 都是ELF文件头部的字段。这些值我们可以通过构造畸形ELF文件来控制。显然这里作者在避免缓冲区越界读取问题,检测 + * ()这个偏移量是否依然在ELF文件大小之内。如果不在,就抛出异常,因为我们的缓冲区只有这么大。作者想到了检查整数溢出,但是他的方法是把和从 int转换成 long。值得注意的是 long的大小是:MSVC下永远是32位整数,gcc和clang下32位ELF就是32位整数,64位ELF就是64位整数。所以如果我们用32位UPX的话,( long) + * ()是可以溢出的,只要足够大,让它们的和大于或等于2^32,它的值就可以小于。

往下:

php整数溢出漏洞_整数溢出漏洞_溢出漏洞怎么利用

268至272行针对不是 ( file)情形,268行的len就是之前258行校验的值,按上文说的len是溢出之后的值,它小于,但是很大。所以到272行phdri= + 又发生整数溢出,phdri会小于。所以如果接下来phdri被用于读取结构体的值,那么读到的实际上是缓冲区以外的值。但是随后发现phdri使用之前会检查是否为0×40。所以这个缓冲区越界读取是触发不了的。

接下来274行以下针对是情形,类似地,因为我们取为一个接近2^32的值,如,这样shdri= ( *)( + );指向的就是内存之前的位置。然后进入e(::)函数:

溢出漏洞怎么利用_整数溢出漏洞_php整数溢出漏洞

for循环内shdri指针被用来读取shdri->的值。这时因为shdri不是一个有效的地址,这里就会触发崩溃。

所以我的PoC就直接把CVE-2017-15056的PoC拿来,把改成3 ()、改成、改成。这样 + * ()的值是,小于。shdri等于 – 0×2000。用32位UPX压缩PoC,就能看到崩溃:

php整数溢出漏洞_溢出漏洞怎么利用_整数溢出漏洞

当然这个整数溢出漏洞只能到拒绝服务为止了,应该是没法远程利用的(比如把内存写到输出文件里)。我也对UPX、ELF文件了解不多,所以就没深入研究其他位置有没有溢出问题。

0×03 修复

我提交了一个Pull 修复这个UPX漏洞,但是他们没用我的PR,他们自己写了一个。对于加法避免整数溢出的方法两种:加法运算的和如果小于任何一个加数,则有溢出:

int add( int a, int b, bool& ) { int = a + b; = ( < a); ; }

另一种是转换成64位无符号整数:

int add( int a, int b, bool& ) { long long = ( long long)a + ( long long)b; int = (); = ( != ); ; }

乘法:转换成64位或者:

int mul( int a, int b, bool& ) { int = a * b; = (a != 0) && ( / a != b); ; } 0×04 参考

~

网络安全学习,我们一起交流

~

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值