在 Twitter 上讨论这个问题相当于现代费马通过边际讨论数学证明。因此,让我们扩展一下 Peter Wullinger 没有足够的空间将其放入Twitter 帖子的空白处。
当然,systemd 人员可以通过其他方式做到这一点:
- 建议系统管理员使用
ssh -x --账户@host systemctl东西……
代替 systemctl -H account @ host stuff …
- 对本地域套接字使用 OpenSSH 的内置转发机制,以便在内部
systemctl
产生类似的东西ssh -xT -L /run/user/用户/账户@host /bus:/run/dbus/system_bus_socket --账户@host / bin /true
而不是(就像它一样) ssh -xT --账户@host systemd -stdio-bridge
实际采用的方法存在许多问题,其中一些与安全相关。然而,到目前为止,似乎没有一个会上升到完全脆弱的程度。
“这个无证systemd-stdio-bridge
程序是什么?”
首先考虑系统管理员查看日志和 的输出ps
,并想知道这些人都systemd-stdio-bridge
通过 SSH运行。从“在我的 VPS 上运行的奇怪的 'agetty' 进程”中可以看出,我们有对Weitse Venema 的agetty
程序感到好奇的人,我们知道MacOS 已经有恶意软件命名systemd
以试图愚弄人们,所以这不是一个延伸也不能不合理地想象系统管理员也会对此感到疑惑systemd-stdio-bridge
。
问题是,这是另一个 systemd 的 doco 比穷更糟糕的情况:它完全不存在。根本没有由 systemd 人员编写的手册页。systemd-stdio-bridge
所以系统管理员的第一选择,就是阅读手册,也无济于事。(这是 systemd 人员有意为之,他们没有包括想要在他们的用例中识别正在运行的程序的系统管理员。)
它可能有助于系统管理员了解该程序经历了一个被调用的阶段,systemd-bus-proxyd
该阶段有一个手册页。它和手册页都从 systemd 中删除了,但是当systemd 开发人员 David Herrmann 后来带回旧程序时,手册页并没有随之恢复。(注意,如果你去挖掘它,旧的手册页systemd-bus-proxyd
并没有正确描述 . 的当前命令行用法systemd-stdio-bridge
。)
如果 systemd 开发人员将 doco 与程序一起考虑,他们可能已经发现了一个当前的错误:systemctl
在某些情况下传递systemd-stdio-bridge
不支持的选项,并支持不使用的systemd-stdio-bridge
不同选项。systemctl
“这是什么未记录的sd_bus_set_address
东西?”
Peter Wullinger 的注释之一是这些都没有记录在案,对于试图求助于阅读systemd-stdio-bridge
程序代码的系统管理员来说,这至少是正确的。这是一个编译的 C 程序,而不是用解释性脚本语言编写的。正如 Peter Wullinger 所指出的,它依赖于调用一个sd_bus_set_address()
函数。 systemd 人员不提供手册页sd_bus_set_address()
,在其他 systemd 手册页上留下悬空的超链接(例如手册页中的超链接)sd_bus_new()
。
解析错误
最初并不清楚 Peter Wullinger 认为什么是“逃避、解析、逃避错误”。但是在幕后进行了大量的解析;其中最重要的是 systemd 的桌面总线库,它在一个地方从它们的组成部分构造诸如“ unixexec:path=ssh,argv1=-xT,argv2=--,argv3=account%40host,argv4=systemd-stdio-bridge,arg5=--machine=fred
”之类的字符串,然后再将它们解析回另一个地方的组成部分。我们从 Daniel J. Bernstein(以及许多其他人)那里了解到,避免解析的设计,包括这种编组为伪人类可读形式,然后解编回机器可读形式,是一个好主意。
事实证明,Peter Wullinger 指的argv2=--
是现在存在的原因。这当然是一个众所周知的问题,很难说它的例证过于广泛。然而,在前面提到的多余的序列化和反序列化中,一个额外的和更微妙的解析相关问题是系统的非常特殊的性质。请注意,要传入的等号字符argv3
被转义为%3d
. 但是,等号登录arg5=--machine=
不会被转义。序列化不遵循与反序列化相同的规则。这样,错误和安全问题就存在了;这是 Daniel J. Bernstein 建议通过不首先进行解析来避免的事情之一。
重新发明轮子
当然,有一种概念systemd-stdio-bridge
是对车轮的重新发明,但它还没有把所有的角落都敲掉以使其足够圆。毕竟,如前所述,OpenSSH 有一个内置机制,被广泛使用和测试,用于通过从远程主机到本地机器的 SSH 连接转发对本地域套接字的访问。(它从 OpenSSH 6.7 开始,在 systemd 开发人员 David Herrmann 重新引入该systemd-stdio-bridge
程序的前一年发布。自 2006 年以来,该程序的补丁就已经存在,比 systemd 存在早几年。)
反对这一点是两件事。
首先:远程生成一个程序,然后通过其标准输入和输出与它通信,通过 SSH 连接传输,这并不是 SSH 的不寻常用途。rexec
毕竟是做事的模式。
第二:必须小心地进行本地域套接字转发。使用标准的 I/O 机制,没有其他 D-Bus 客户端程序可以(缺少调试访问等技巧)使用转发机制将自己连接到远程 D-Bus 代理。然而,上述机制必须小心:
- 不允许用户以外的任何人访问,以便只有用户(和超级用户)的进程可以访问本地代理套接字
/run/user/user/account@host/
- 防止用户以外的其他人可写,这样其他人就不会出现并偷偷地用符号链接替换或执行其他此类技巧
/run/user/user/
/run/user/user/account@host
- 注意不要在多次调用之间发生冲突(这可以通过使用本地唯一名称而不是仅仅来完成)
/run/user/user/account@host/bus
systemctl
bus
进一步阅读