Mikrotik SMB 缓冲区溢出漏洞复现

固件安全
2022-10-20 10:29
70660

最近需要去研究一下MikroTik,所以来复现一下它的经典漏洞。

漏洞简介

漏洞出现在MikroTik路由器所使用的MikroTik公司自研的一款操作系统routerOS。

MikroTik是一家拉脱维亚公司,成立于1996年,旨在开发路由器和无线ISP系统。MikroTik现在为世界上大多数国家的互联网连接提供硬件和软件。RouterOS是MikroTik基于Linux v3.3.5内核的独立操作系统。

在MikroTik RouterOS SMB服务中发现缓冲区溢出。访问该服务的远程攻击者可以利用此漏洞并在系统上执行代码。溢出发生在身份验证之前,因此未经身份验证的远程攻击者可能会利用它进行攻击

然后简单了解一下SMB服务是个什么东西(来自百度百科):

SMB 一种客户机/服务器、请求/响应协议。通过 SMB 协议,客户端应用程序可以在各种网络环境下读、写服务器上的文件,以及对服务器程序提出服务请求。此外通过 SMB 协议,应用程序可以访问远程服务器端的文件、以及打印机、邮件槽(mailslot)、命名管道(named pipe)等资源。

在 TCP/IP 环境下,客户机通过 NetBIOS over TCP/IP(或 NetBEUI/TCP 或 SPX/IPX)连接服务器。一旦连接成功,客户机可发送 SMB 命令到服务器上,从而客户机能够访问共享目录、打开文件、读写文件,以及一切在文件系统上能做的所有事情。

环境搭建

首先到官网下载好vmdk文件,然后新建一个虚拟机用来装routerOS操作系统

首先新建虚拟机然后选择稍后安装操作系统:

选择内核的时候记得使用3.x

然后随便起个名字,这里我直接用mikrotik了

处理器和内核都指定1个就够了,内存也不用太大,routerOS毕竟大部分时候运行在小路由器上,所以对硬件要求不高,网络类型的话使用NET就可以。

磁盘选择这个:

使用现有磁盘:

然后将之前下载好的指定版本的磁盘文件选中

最后打开虚拟机,输入用户名admin,密码是空,即可进入到一个shell界面

在shell界面输入:

ip smb set enabled=yes
ip address print

第一行是把smb服务启动,第二行是查看一下ip

接下来是开启telnet,由于现在虚拟机里的shell并不是linux的shell,并不是很方便。使用github上写好的项目

项目地址:https://github.com/0ki/mikrotik-tools

运行脚本可以一把梭开启telnet

成功开启后会有如下提示

我们使用devel登录一下telnet试试:

可以看到已经能够在刚才搭建好的OS上执行linux命令了。最后用netstat检查一下是否开启了smb服务:

也可以用nmap确认一下:

这里的139端口下的netbios-ssn指的就是smb服务

至此整个环境的搭建就基本结束了,下面开始漏洞复现

漏洞复现

首先要做的肯定是找到smb这个服务是靠哪个二进制程序开启的,有了telnet是真的方便了很多:

这里基本可以确定了smb服务应该就是/nova/bin/smb开启的,所以需要将这个文件拿出来进行逆向分析,问题又来了,该怎么拿呢,我们并没有往routerOS那个虚拟机中安装vmtools。

其中一个方法是利用ftp服务,但是多少有点麻烦,既然有linux命令了,不如直接nc你说是吧,在自己的环境里执行:

nc -lp 1234 > out

然后在telnet里执行:

nc -w 3 192.168.58.135 1234 < /nova/bin/smb

可以看到smb已经成功被我们搞出来了,非常简单方便:

漏洞主要出现在sub_806B11C函数中,这个函数是开启一个新的smb连接,这也意味着我们无须验证就可以直接触发,不需要进行登录绕过:

v41是栈上的缓冲区,第二个参数暂时还不清楚,点进来分析一下:

在while循环中不断执行复制,复制长度位v2,这里并没有对v2做出限制,意味着我们输入的是\xff,它就允许复制0xff个字节进去,但是栈上并没有这么大的空间,于是导致了栈溢出,这里我更倾向这个洞是fuzz出来的,也有可能是我对这个系统并不熟悉的缘故。

想要到达这段代码,就需要有一定的smb服务的基础,可以参考这个:
https://blog.csdn.net/vevenlcf/article/details/17716053

定义如下:

UCHAR Type; // Type of the packet
UCHAR Flags; // Flags
USHORT Length; // Count of data bytes (netbios header not included)

“Flags”域的值总是被置为0。

“Type”域有几种可能的选择:

0x81 对应一个NETBIOS会话请求。这个代码在客户端发送它的NETBIOS名字到服务器是使用。

0x82 对应一个NETBIOS会话应答。这个代码在服务器向客户端批准NETBIOS会话时使用。

0x00 对应一个会话消息。这个代码总是在SMB会话中被使用。

“Length”域包含了数据字节的长度(NETBIOS头部没有被包含在内)。

通过cyclic来确认返回地址的偏移是99,这意味着我们可以精准的控制返回地址了,接下来寻找gadget,由于smb程序并没有链接libc,所以没有system函数可以直接使用,但是可以用syscall

有了syscall,接下来需要控制eax,ebx,ecx,edx

通过如图所示的两个gadget,可以完美控制syscall的所需参数,由于执行write或者exec这类系统调用,我们不容易直观的看到效果,所以直接选择调用reboot来尝试让虚拟机重启,要注意一件事情,reboot需要两个magic number,并且还有一个cmd参数要填:

所以这里如果想让机器自动重启,需要让rdx等于0x1234567
让rbx和ecx分别等于对应的magic number,即:

eax=88

ebx=0xfee1dead

ecx=672274793

edx=0x1234567

poc就留给读者自行完成吧,最后的效果如下

分享到

参与评论

0 / 200

全部评论 6

zebra的头像
学习大佬思路
2023-03-19 12:15
Hacking_Hui的头像
学习了
2023-02-01 14:20
iotstudy的头像
师傅,再请教一下。网上的帖子都是reboot的,试了一下execve,但不行。由于可执行程序中没有"/bin/sh"或"sh"可用,采用字符串拼接的方法,即shaddr=next(elf.search(b'sh\x00')),最终凑成了execve('sh',0,0),但无法获取shell。execve是不是不能这么用?
2022-10-31 08:20
Ayaka的头像
从我个人的实践经验来看,system('sh',0,0)是可以替代system('/bin/sh',0,0)的,但是execve的话不行,具体原因我没有研究过
2022-10-31 09:17
iotstudy的头像
师傅,请教一下。为啥要用ROPgadget搜索syscall,syscall是x64用的吧?32位用的是int 80,是这样吗?smb程序是32位的呀。
2022-10-28 08:36
Ayaka的头像
woc这里写的有问题,感谢师傅发现,确实应该使用int 0x80,写的时候脑子坏掉了
2022-10-28 10:18
iotstudy的头像
哈哈哈,我就是来免费刷平台点击率的。
2022-10-30 11:09
iotstudy的头像
师傅,看了一下网上的帖子,基本都是reboot的利用方式。想execve搞一下,没看到“/bin/sh”可用,就使用shaddr=next(elf.search(b'sh\x00')) 命令拼接了一个sh字符串,即execve("sh",0,0),但无法获取shell,exeve没有这种用法对吧?
2022-10-30 21:28
iotstudy的头像
漏洞名称:CVE-2018-7445 漏洞版本:漏洞版本的iso镜像在官网上应该是找不到了。
2022-10-24 09:12
iotstudy的头像
看着真着急,让我来补充一些漏洞其他信息: 漏洞名称:CVE-2018-7445 漏洞版本:mikrotik-6.40.6.iso x86版本 下载地址:https://mikrotik.com/download
2022-10-24 08:59
Ayaka的头像
哈哈谢谢啦,镜像是能够下到的,不过需要直接用url去下载,url是https://download2.mikrotik.com/routeros/6.40.5/mikrotik-6.40.5.iso
2022-10-25 21:32
iotstudy的头像
好的,感谢,我去下载一下看看。
2022-10-26 08:19
投稿
签到
联系我们
关于我们