18

我正在编写一组实用程序,bash其中包含一个公共库。我编写的每个脚本都必须有一段代码来确定库相对于可执行文件的路径。不是实际代码,而是一个示例:

#!/bin/bash

DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
. $DIR/../lib/utilities/functions

我没有尝试搜索库的序言,而是使用环境变量来指示库位置的好主意。

#!/bin/bash

. $TOOLS_LIBRARY_PATH

我可以使用包装程序来设置该环境变量,或者我可以将它设置在我自己的路径中。可能有更好的方法来组织bash工具集,但问题是:

我可以信任我的环境变量吗?

这是其中之一,我从来没有真正考虑过这种问题。当用其他语言编程时,路径被用来查找库,(例如LD_LIBRARY_PATH, PYTHONPATH, PERLLIB, RUBYLIB, CLASSPATH, NODE_PATH),但我从来没有停下来想一想这怎么可能是不安全的。

事实上,LD_LIBRARY_PATHWhyLD_LIBRARY_PATH不好阻止它的使用。如果分别调用 Ruby 和 Perl 库路径环境变量$SAFE-T(污点模式)的安全机制,则忽略它们。

到目前为止我的想法...

  • 用户可以设置TOOLS_PATH_LIBRARY为他们选择的库,但该实用程序将在他们的 uid 下运行。他们可以直接使用bash.
  • 我的工具sudo有些东西。有人可以将他们设置TOOLS_PATH_LIBRARY为利用这一点的东西。但是,这些工具不是通过 运行的,它们只是在这里和那里sudo调用。sudo无论如何,用户都必须是一个sudoer,他们可以直接调用sudo
  • 如果我不能信任TOOLS_PATH_LIBRARY,那么我就不能信任PATH。所有程序调用都必须使用绝对路径。
  • 我见过 shell 程序为绝对的程序使用别名,所以不要调用ls,而是使用变量,比如LS=/bin/ls. 根据我的阅读,这是为了防止用户将程序默认值重新定义为别名。请参阅:PATH、功能和安全性。Bash 脚本最佳实践。 .
  • Perl 的污染模式将所有环境变量视为“污染”,这是不祥之兆,这就是为什么我试图推理环境风险的原因。
  • 一个用户不可能更改另一个用户的环境,除非该用户是 root。因此,我只关心用户更改自己的环境以提升权限。请参阅:有没有办法更改另一个进程的环境变量?

我已经把变成了各种各样的答案,但我仍然会发布它,因为它不是一个简单的答案。

更新:围绕使用环境变量指定库和可执行文件路径的安全问题是什么?

4

3 回答 3

4

虽然各种程序中存在防止修改环境变量的机制,但底线是,不,你不能信任环境变量。安全问题是非常基本的:

每当用户可以更改预期执行的内容时,就会出现漏洞被利用的可能性。

举个例子,看看CVE-2010-3847。这样,对包含 setuid 或 setgid 二进制文件的文件系统具有写访问权限的低权限攻击者可以使用此漏洞来提升他们的权限。它涉及由用户修改的环境变量。

CVE-2011-1095是另一个示例,不涉及 SUID 二进制文件。在谷歌上搜索“glibc cve environment”,看看人们可以通过修改环境变量来做哪些事情。相当狡猾。

您的担忧实际上归结为您的以下陈述:

用户可以将 TOOLS_PATH_LIBRARY 设置为他们选择的库,但该实用程序将在他们的 uid 下运行。他们可以直接使用 bash 运行他们的恶意库。

这里的关键词——运行他们的恶意库。这假设他们的库也归他们的 UID 所有。

这就是安全框架将为您带来很多好处的地方。我写的一篇专门针对这个问题,你可以在这里找到:

https://github.com/cormander/tpe-lkm

该模块停止对可写文件或不属于受信任用户 (root) 的文件的 execve/mmap/mprotect 调用。只要他们不能将恶意代码放入受信任用户拥有的文件/目录中,他们就不能以这种方式利用系统。

如果您使用包含这些变量的 SUID 二进制文件或 sudo,您可能需要考虑启用“偏执”和“严格”选项以阻止 root 甚至信任非 root 拥有的二进制文件。

我应该提到,这种可信路径执行方法可以保护使用二进制文件和共享库的直接执行。它对解释语言几乎没有(如果有的话),因为它们解析字节码而不直接执行它。因此,您仍然需要对, , 等进行一定程度的关注PYTHONPATH,并使用您提到的语言的安全机制。PERLLIBCLASSPATH

于 2012-04-10T14:50:02.943 回答
2

简短的回答:

假设用户无论如何都能够运行她自己选择的程序和代码,那么您不必信任他们提供给您的任何东西,包括环境。如果帐户在某些方面受到限制(没有 shell 访问权限,没有对允许执行的文件系统的写访问权限),那可能会改变情况,但只要您的脚本只做用户自己可以做的事情,为什么要防止恶意软件干涉?


更长的答案:

就安全问题而言,至少有两个单独的问题需要考虑:

  • 我们需要防范什么和谁?
    • (密切相关的问题:我们的程序实际上可以做什么以及它可能会破坏什么?)
  • 我们如何做到这一点?

如果并且只要您的程序在启动程序并提供所有输入的用户的用户 ID 下运行(即,唯一可以发起任何攻击的用户),那么只有在极少数情况下,强化是有意义的反攻击程序。我想到了反复制保护和共享高分,但这组事情不仅与输入有关,而且可能更与阻止用户阅读代码和内存有关。在没有某种 suid/sgid 技巧的情况下隐藏 shell 脚本的代码是我不知道该怎么做的;我能想到的最好的办法就是模糊代码。

在这种情况下,用户可以欺骗程序做的任何事情,他们也可以在没有工具的帮助下做,所以试图“保护”免受该用户的攻击是没有实际意义的。您的描述并不像您实际上需要任何针对攻击的保护一样。


假设您确实需要保护,您根本不能依赖环境变量 - 如果您无法重置诸如LD_LIBRARY_PATHand之类的东西LD_PRELOAD,甚至调用具有绝对路径的工具,例如/bin/idor/bin/ls不会给您可靠的答案,除非该工具恰好是静态编译的。这就是为什么默认启用以及为什么运行 suid 程序必须忽略某些环境变量的原因sudoenv_reset请注意,这意味着您的观点TOOLS_PATH_LIBRARYPATH同样值得信赖在您的情况下可能是正确的,但在其他情况的边界情况下不一定是正确的:系统管理员可能会重置PATH使用sudo,但让非标准环境变量通过。

如上所述,argv[0](或其 bash 等效项${BASH_SOURCE[0]})并不比环境变量更可靠。用户不仅可以简单地制作原始文件的副本或符号链接;execve或 bashexec -a foo bar允许将任何内容放入argv[0].

于 2012-04-10T17:12:04.400 回答
0

你永远不能相信别人的环境。

为什么不简单地创建一个包含所有这些重要代码的新用户。然后,您可以直接从中获取信息,也可以/etc/passwd使用~foo语法查找用户的主目录。

# One way to get home directory of util_user
DIR=$(/usr/bin/awk -F: '$1 == "util_user" {print $6}' /etc/passwd)

# Another way which works in BASH and Kornshell
[ -d ~util_dir ] && DIR=~util_dir


# Make sure DIR is set!
if  [ -z "$DIR" ]
then
   echo "Something's wrong!"
   exit
fi
于 2012-04-10T18:55:34.447 回答