freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课
FreeBuf+小程序

FreeBuf+小程序

官方公众号企业安全新浪微博

国内领先的互联网安全新媒体,同时也是爱好者们交流与分享安全技术的社区

MEDCIN引擎的漏洞利用详解 金币
2016-01-12 09:00:17

*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。

科普:MEDCIN引擎是一款服务于医生护士的电子病历系统。

几个月前,我在MEDCIN引擎旧版本的安全评估中发现了一个漏洞。于是我向供应商报告了该漏洞然后修复了,之后在查看该程序的最新代码时又发现了几个漏洞。

这个程序之前的旧版本里漏洞是不需要经过身份验证就可以处理来自远程客户端的邮件还可以在Windows上运行系统级权限的服务。而且,原来的二进制文件也缺少编译时的内存保护。于是我首先检查了开发商是否将编译时的内存保护功能放入他们的最新版本。快速浏览了几个任意函数,我看到栈cookies已经被添加了而且下图中二进制文件也被SafeSEH编译。有了这些新的保护措施,任何基于堆栈的缓冲器溢出漏洞将更难被利用。

于是我使用各种曾在原始的可执行文件中调查出来的信息解析例程进行跟踪。配合之前在二进制文件上的操作,我快速编写了一个简单的模糊器向应用程序服务提供随机数据。几个星期的模糊测试和静态分析后我找到了8个代码执行漏洞。这些bug中包括栈、堆、数据段缓冲器溢出、内存泄露以及控制部分任意内存的写入。

CVE-2015-2898

调查了一堆漏洞后,我决定开始着手于一开始发现的基于堆栈的缓冲区溢出。可是栈cookies与SafeSEH编译的二进制文件的结合并不能让我们从应用程序获得可执行文件的控制权。那么如果不能泄漏栈的cookie,我就没办法利用这个漏洞。

CVE-2015-2901

接下来的一个bug是字符串缓冲寄存器溢出到数据段再通过socket泄漏。这个漏洞很有用,因为不仅可以覆盖到整个数据段还能从数据段返回给我内存地址。不过这个漏洞有一个明显的限制范围,我只能覆盖数据段的空字节。下图是漏洞的伪代码。

花了很多时间和精力,还是没有办法仅仅通过这个漏洞来获得执行的控制权。我发现只有当数据段被损坏或者程序崩溃的时候会有一个很短暂的时间让我们通过。但是,程序崩溃的情况是随机的而且常常没有办法进入。我也没办法让栈cookie或栈地址泄漏。但是!能泄漏出一些非常有用的堆地址。

CVE-2015-2900

然后我将目光转移到能控制部分任意内存写入的漏洞。这个特殊的bug是在一次模糊器运行中发生程序崩溃时发现的。它似乎来自于添加到数据段中堆指针地址的用户控制的索引(带符号的整数)。里面的函数还不能验证传入的整数是否大于零。不过我认为该漏洞是部分控制的原因是因为添加索引的堆地址是动态的。下面是bug的一些伪代码。

经过一番调查,我发现存放我们控制的索引的堆地址在CVE-2015-2901的字符串连接缓冲寄存器的下方。这意味着,我们可以泄漏这个地址并完全控制发生写入的位置。正如代码片段中看到的,被写入的值是一个堆指针,在任意写入之前就被分配好了。

现在既然我们可以在存储器的任何地方写一个指针,那么接下来要做的就是确定我们是否控制着指针指向的数据并找到一个有用的目标地址以重写我们的指针。确定后,我们重写一个函数指针触发命令获取代码执行。不过前提是假设指针指向的数据是可以控制执行的。

通过搜索二进制文件,我只找到极少数位于静态位置的函数指针。幸运的是这些函数指针中有一个可以直接访问信息解析函数。哇!我们似乎已经在堆上实现了代码执行。

这能运行的原因是因为该应用程序并没有在数据执行保护下编译。我就在Windows 7系统上将DEP设置为“接受”。大多数人只知道DEP禁用栈上的执行,但是它也保护着堆。

实现代码执行后,现在必须弄清楚被我们重写的函数指针指向的数据到底被控制了多少。我看了一下代码,发现虽然我很好地控制住了缓存器,但在缓冲器里还是超过了0x100个字节。每次置换我都尝试从不能控制的地方跳转到缓冲器中我们的控制部分,但是都失败了。那有其他的漏洞让我们做到么?

CVE-2015-2899

这个漏洞是实现代码执行如何控制重写的函数指针所指向的数据的最后一个障碍。既然我们的数据在堆上,那么下一步就是看看是否能以某种方式直接溢出堆分配从而用可控的数据来填充它。所幸,我们正好有一个堆缓冲器溢出。

在上图中,我们有一个经典的堆缓冲器溢出,因为目标缓冲器的大小是静态的而且源字符串的长度不会被检测。于是我决定尝试以内存分配溢出到我的目标分配的方法来创建一个堆,这样重写的函数指针就会指向控制的数据。

在这里我需要让内存持续分配不被释放,最好还能控制大小。终于,我在一堆信息分析函数中找到了一个函数可以让我随便分配内存。在没有对Windows 7的堆分配器进行真正研究的情况下,我直接测试哪些大小和分配数量是能达到我的需求。下面是我观点验证程序的一般结构。

 正如预期的那样,由于不清楚windows 7的堆分配器的内部工作原理,我的成果相当不可靠。另外,我还不清楚是否有其他内存的分配和释放在我的控制之外。于是我需要一个能监视分配器分配和释放的可视化工具。

正当我在为网上找到一个堆监视工具而高兴时。我发现这些竟然都不是我想要的!他们要么就是拿内存快照然后让你分析,要么就被嵌入在一个调试器里。我本还希望和库hooking起来的函数不仅能共享还能运行64位。

不过我在网上找到一个叫Heapy的工具的源代码。它使用了一个名叫MinHook的开源hooking库来支持钩子函数,还支持x86和x64体系结构。它也有hooking动态内存分配的示例代码。于是我决定用这个MinHook来作为我工具的一部分。

堆监视器

有了新的堆分配可视化工具和代码,我开始使用HeapMonitor(自己起的名儿)。我首先在DLL注入器写入代码连接一个服务级别的进程。然后我改变策略,将钩子细节写到一个文件里去而不是通过socket传送。这样就可以让我的可视化GUI界面在所有系统上都适用。我还附加一个栈跟踪方便追踪负责调用的函数。

我决定用我最熟悉的Java写GUI。我在界面的右侧列表中实时显示分配和释放。主框架是显示内存分页的块状视图,也会实时更新信息。主框架上的第二个选项卡列出了所有列表中被选的分配和释放的栈追踪。为了防止分配的内存页出现划分问题,我还在上端添加了内存导航栏通过内存快速导航。

为了更好地处理Windows 7堆分配器的内部工作,我查找了不少安全报告。其中对我工具最有用是Chris Valasek的“了解低碎片堆”, Steven Seeley的“分配器里的幽灵”,和Jeremy Fetiveau的“利用低碎片堆获取利润和乐趣”。通过我的堆可视化工具也证实了他们的研究。

CVE-2015-6006

在我操作里有一个很大的问题,每当我把分配设置为连续分配就总是会在达到0x1000个字节后自动关闭。这意味着,我的堆溢出必须相当大。在查看了关于Windows 7上堆分配器的最新研究后,我意识到这不正是因为启用了低碎片堆么。之后通过堆监视器工具也证实了这一点。但是我依然没办法分配同样的大小,因为CVE-2015-2899是静态的,0XF0,和CVE-2015-2900必须至少0x100个字节(passed_alloc_size + 0x100)。

当我做到最后的时候,我承认要达到大致上100%的可靠性是不可能的。非常碰巧的是针对任意写入漏洞(CVE-2015-2900)的调用函数有两个bug。它在用户提供的数据传递到任意写入函数分配缓冲器之前就截断成16位有符号的short型。该函数返回后,就将所有的用户数据以字符串的形式拷贝到新创建的缓冲器。这意味着我们可以提供一个大于MAX_SHORT字符串导致之后的字符串拷贝发生堆溢出。这也意味着我们可以控制分配的大小。下图是漏洞的代码。

一旦低碎片堆被激活,我就能在按序分配中创建缺口并重新分配他们用于我的堆溢出。调整了一些额外的内存分配我的攻击几乎100%可行!

有兴趣的话你可以在这里可以获得堆监视器工具和源代码。

这里获得完整的概念和Metasploit模块。

*参考来源:securifera,FB小编江湖小吓编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

本文作者:, 转载请注明来自FreeBuf.COM

# 漏洞 # 引擎 # MEDCIN # 电子病历 # 系统
被以下专栏收录,发现更多精彩内容
+ 收入我的专栏
评论 按时间排序

登录/注册后在FreeBuf发布内容哦

相关推荐
  • 0 文章数
  • 0 评论数
  • 0 关注者
登录 / 注册后在FreeBuf发布内容哦