通过流程环境传递敏感数据是否安全?

信息安全 linux Unix 保密
2021-08-10 17:11:30

最近,我一直在寻找在不通过命令行或不使用文件系统条目的情况下将敏感信息从一个进程传递到另一个进程(在进程启动时)的可能性。这是在 Linux 上,但这个问题也适用于其他系统。

特别是,访问 MySQL 服务器的密码应从脚本传递到 MySQL 客户端。为此,您可以通过命令行-pPASSWORD在这种精确的情况下,MySQL 客户端程序非常友好,可以覆盖命令行文本,将可见的密码字符串替换为 ,XXX但这是一个很糟糕的解决方案。

我考虑改用进程环境。该脚本在进程环境中设置密码,然后启动的子进程可以从那里读取它。事实上,MySQL 客户端允许这样做并查找环境变量MYSQL_PWD这看起来非常安全且优雅,因为除了 root 和流程所有者之外的任何人都无法咨询流程环境,至少据我所知。

但是,MySQL 5.1 手册指出:

这种 [通过环境] 指定 MySQL 密码的方法必须被认为是极其不安全的,不应使用。某些版本ps包括一个选项来显示正在运行的进程的环境。在某些系统上,如果您设置MYSQL_PWD,您的密码会暴露给任何其他运行 ps 的用户。即使在没有这种版本的系统上ps,假设没有其他方法可供用户检查进程环境也是不明智的。”

那么问题是:通过流程环境传递敏感数据真的不安全吗?是否有系统允许在不验证权限的情况下咨询另一个进程的环境?显然,超级用户可以随意获取密码,但话又说回来,他一开始就不需要它。

4个回答

回答我自己的问题:

似乎某些系统正在,或者说确实是不安全的,将环境信息泄露给其他进程。

用户“mitchblank”在 github 上为“mosh”应用程序(移动外壳)提出了与当前问题类似的问题。作者写道:

背景:在过程映像中,argv[] 和 envp[] 以相同的方式存储,彼此相邻。在“经典”UNIX 中,/usr/bin/ps 通常是 setgid “kmem”(或类似组),这允许它在 /dev/kmem 中挖掘以读取有关活动进程的信息。这包括读取系统上所有用户的进程参数和环境的能力。

这些天来,这些“特权 ps hack”在很大程度上已经落后于我们:UNIX 系统都提出了查询此类信息的不同方式(Linux 上的 /proc 等)我认为所有这些(?)都认为进程的环境只是可读的通过它的 uid。因此,环境中的密码等安全敏感数据不会泄露。但是,旧方法并非 100% 死掉。举个例子,这里有一个我可以访问的 AIX 5.2 机器的例子......”

……

今天,mosh 似乎只出现在 Linux/OSX/FreeBSD 上,但如果它流行起来,恐怕它最终会出现在仍然使用老式 UNIX“每个人都可以看到任何人的环境变量”模型的某个平台上。

我无法确认是否存在任何允许泄漏环境变量的系统(历史学家和有权访问旧安装的人的工作。)

环顾四周表明,在 2000 年,环境变量确实被认为是敏感的,即可能会标记潜在问题,请参阅CERT 漏洞 22404确实,上面提到的 AIX 5.2 的弱点是一个错误(自修复以来。不幸的是,除了这个IBM 技术公告之外,我在 Internet 上没有关于此的详细信息)

CERTRISKS 论坛对环境变量以不安全的方式实施或在任何时间点被利用一无所获。

我不确定其他程序是否传递敏感数据(GPG 没有),但 MySQL 手册的警告似乎过分了。

user@example(pts/1)$ cd /proc/1022 
user@example(pts/1)$ ls -lha environ 
-r-------- 1 root root 0 Jul 22 17:20 environ

因此,在 Linux 上它是安全的。它在其他类 UNIX 操作系统上可能不安全......

除非你不能信任root,否则所有的赌注都没有了。

过去的传统观念是:不,环境不安全。不要通过环境传递秘密。

我不知道旧的传统智慧是否仍然适用。至少在最新版本的 Linux 上,一个进程似乎不再可能查看另一个进程的环境(如果它们由不同的用户拥有)。但是,我不知道其他操作系统是做什么的。我对通过环境传递秘密非常谨慎;这听起来不像我相信所有操作系统都会保护的那种东西。

更安全的解决方案:设置管道(如果两个进程具有某种父子关系),或者使用进程间通信(IPC),或者将其存储在其他人无法读取的私有文件中。最佳解决方案可能取决于您的具体情况。如果您正在编写应用程序代码,您可能会考虑前两种机制之一。如果您正在编写一个 shell 脚本,最简单的可能是将其存储在一个私有文件中,该文件的权限已设置为确保没有其他人可以读取它。至少那是我会做的——尽管我总是可能过于保守。

当然,如果您正在编写一个只需要在单个系统上运行的脚本,那么您可以测试该系统以查看其他人是否可以查看该环境。但是,如果您正在编写广泛使用的通用代码,我会倾向于上一段中的解决方案,而不是通过环境传递秘密——尽管我承认我不能指出任何使用环境确实不安全的现代系统.

想象一下,您正在运行一个 Web/应用程序服务器,该服务器通过环境变量提供数据库密码(您这样做是为了避免将密码存储在磁盘上,例如)。如果您的服务器/网站存在允许攻击者读取任意文件的未知漏洞(例如:路径遍历……),它可能能够读取/prod/[THE_PID]/environ. 如果您在 Docker 容器中运行您的服务器,攻击者可能很容易猜出您的进程服务器的 PID(可能是 PID 1)。在这种情况下,通过标准输入传递密码看起来更安全(如果可以的话)。