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

时间:2012-04-10 13:45:57

标签: security bash unix environment-variables

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

#!/bin/bash

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

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

#!/bin/bash

. $TOOLS_LIBRARY_PATH

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

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

这是其中之一,我从来没有真正考虑过这类问题。使用其他语言编程时,路径用于查找库(例如LD_LIBRARY_PATHPYTHONPATHPERLLIBRUBYLIBCLASSPATHNODE_PATH ),但我从来没有停下来思考这可能是不安全的。

事实上,LD_LIBRARY_PATHWhy LD_LIBRARY_PATH is bad来阻止其使用。如果分别调用$SAFE-T (taint mode)安全机制,则忽略Ruby和Perl库路径环境变量。

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

  • 用户可以将TOOLS_PATH_LIBRARY设置为他们选择的库,但该实用程序将在他们的uid下运行。他们可以直接使用bash运行恶意库。
  • 我的工具sudo有些事情。有人可以将TOOLS_PATH_LIBRARY设置为利用此功能的东西。但是,这些工具不是通过sudo运行的,它们只在这里和那里调用sudo。在任何情况下,用户都必须是sudoer,他们可以直接致电sudo
  • 如果我不相信TOOLS_PATH_LIBRARY,那么我就不相信PATH。所有程序调用都必须使用绝对路径。
  • 我见过shell程序对绝对程序使用别名,因此不要调用ls,而是使用变量,如LS=/bin/ls。根据我的阅读,这是为了防止用户将程序默认值重新定义为别名。请参阅:PATH, functions and security. Bash scripting best practices.
  • Perl的taint mode将所有环境变量视为“污染”,这是预感,这就是我试图推断环境风险的原因。
  • 除非该用户是root用户,否则一个用户无法更改其他用户的环境。因此,我只关心用户更改自己的环境以升级权限。请参阅:Is there a way to change another process's environment variables?

我已经rubber ducked这个问题得到了答案,但我仍然会发布它,因为它不是一个轻松的答案。

更新:使用环境变量指定库和可执行文件的路径有哪些安全问题?

3 个答案:

答案 0 :(得分:3)

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

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

案例分析,请查看CVE-2010-3847。这样,对包含setuid或setgid二进制文件的文件系统具有写访问权限的弱势攻击者可以利用此漏洞升级其权限。它涉及由用户修改的环境变量。

CVE-2011-1095是另一个例子,不涉及SUID二进制文件。谷歌搜索“glibc cve环境”,看看人们可以通过环境变量修改做些什么。非常狡猾。

你的担忧真的归结为你的陈述:

  

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

此处的关键词 - 运行其恶意库。这假设他们的库也由他们的UID拥有。

这是安全框架对您有益的地方。我写的一个专注于这个问题的你可以在这里找到:

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

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

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

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

答案 1 :(得分:1)

简短回答:

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


更长的答案:

在安全问题方面至少需要考虑两个问题:

  • 我们需要防范什么和谁?
    • (密切相关的问题:我们的计划实际上可以做什么以及它可能会破坏什么?)
  • 我们怎么做?

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

在这种情况下,用户可以欺骗程序进行操作,他们也可以在没有工具帮助的情况下进行操作,因此试图“保护”这个用户的攻击是没有意义的。您的描述并不像您实际需要任何防御攻击一样。


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

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

答案 2 :(得分: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