Fuzz AFDKO Crashes 分析

 

这个同样是一周前clone的最新库fuzz结果

问题出现在svread.c中的parseSVG执行strncpy复制前长度判断不严。

 

crash结果

首先来看一下批处理crash发现的gdb结果

Program received signal SIGSEGV, Segmentation fault.
0x0000000000496010 in parseSVG (h=0x998c5a43686190bf) at ../../../../../source/svread/svread.c:864
864        while (!(h->flags & SEEN_END)) {
#0  0x0000000000496010 in parseSVG (h=0x998c5a43686190bf) at ../../../../../source/svread/svread.c:864
#1  0x0d895f8642801ab0 in ?? ()
#2  0x330ad0e8e8e8e8a7 in ?? ()
#3  0x000000000a24ddef in ?? ()
#4  0x0000000000581468 in ?? ()
#5  0x0000000000000008 in ?? ()
#6  0x000000000a20e078 in ?? ()
#7  0x0000000000000000 in ?? ()
Dump of assembler code from 0x496010 to 0x496020:
=> 0x0000000000496010 <parseSVG+432>:    mov    0xcd28(%rax),%ecx
   0x0000000000496016 <parseSVG+438>:    and    $0x1,%ecx
   0x0000000000496019 <parseSVG+441>:    mov    %ecx,%esi
   0x000000000049601b <parseSVG+443>:    mov    %ecx,-0x148(%rbp)
End of assembler dump.
rax            0x998c5a43686190bf    -7382426443606552385
rbx            0x0    0
rcx            0xffffffdd    4294967261
rdx            0x0    0
rsi            0x0    0
rdi            0x0    0
rbp            0x7fffffffdca0    0x7fffffffdca0
rsp            0x7fffffffda30    0x7fffffffda30
r8             0x0    0
r9             0xfffffffffffffff    1152921504606846975
r10            0x0    0
r11            0x7ffff703c5e0    140737337607648
r12            0x404c40    4213824
r13            0x7fffffffe180    140737488347520
r14            0x0    0
r15            0x0    0
rip            0x496010    0x496010 <parseSVG+432>
eflags         0x10246    [ PF ZF IF RF ]
cs             0x33    51
ss             0x2b    43
ds             0x0    0
es             0x0    0
fs             0x0    0
gs             0x0    0
A debugging session is active.

    Inferior 1 [process 120570] will be killed.

Quit anyway? (y or n) [answered Y; input not from terminal]
[+] crash file ===> ./crashes/SIGSEGV.PC.7f8e371974d9.STACK.badbad0d4cce199d.CODE.128.ADDR.(nil).INSTR.[NOT_MMAPED].2019-07-24.18:05:33.75589.fuzz
===========================================================

 

原理分析

调试,运行,崩溃

查看一下相关变量

pwndbg> p/x h->flags
Cannot access memory at address 0x998c5a4368625de7
pwndbg> p/x h
$1 = 0x998c5a43686190bf

查看一下内存布局

所以h作为一个指针,这个地址,肯定是错的

下断点,重新调试

看一下没出问题前h的值

指向这个堆

目前没有任何问题,但从刚刚崩溃中可以看到h的值会被修改为一个无效地址

所以监控一下h的值,如果发生变化,就断下

pwndbg> watch h!=0xa228030

继续执行

在执行strncpy时断下来了,看一下调用栈,并定位一下出错代码

好了,出错位置找到了

在这个位置下一个断点,重新执行

看看执行这句后会有什么效果

h已经变为了一个无效指针。

来看看为什么,重点在strncpy函数

strncpy(tempVal, tk->val + 1, tk->length - 2);

其中tempVal定义

char tempVal[kMaxName];

kMaxName定义

#define kMaxName 64

tempVal是一个64字节长度的字符数组

再来看看tk->length - 2数据

pwndbg> p/x tk->length-2
$6 = 0xab
pwndbg> p tk->length-2
$7 = 171

所以tempVal数组执行完strncpy是会溢出的

那溢出一定会覆盖h的值吗?答案是不一定,看你使用什么编译器了。

经过多次测试发现,如果使用gcc编译,那么就不会被覆盖,如果使用clang编译就会被覆盖至于为什么,其实直接看反汇编代码就懂了

gcc编译

clang编译

可以发现gcch这种重要的数据结构放在了距离rbp更远的地方,减少了被覆盖的风险。

利用这个漏洞,攻击者通过构建特定结构的svg的字体文件,很有可能会造成命令执行

 

总结

很不幸,分析完之后,发现利用afdko的最新代码并不能复现!

经过多次测试,发现afdko通过commit 973a8c929b4fb204dd8fcc84cd12ff02c1ea8aab

把这个洞给堵上了,堵上的原理就是,利用的poc.svg在执行到strncpy前就被断了。

但这个漏洞理论上还是存在的,因为strncpy执行前,现有代码还是没有对长度进行判断,但要是想绕过的话,需要进一步fuzz出能够触发这个洞的poc数据

连续两个洞,都是因为这一个commit,导致无法利用,真是心塞啊

(完)