我在bash
中编写了一个实用程序集合,它有一个公共库。我编写的每个脚本都必须有一个代码块来确定库相对于可执行文件的路径。不是实际的代码,而是一个示例:
# !/bin/bash
DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
. $DIR/../lib/utilities/functions
我有一个聪明的想法,使用一个环境变量来指示库的位置,而不是试图搜索库的序言。
# !/bin/bash
. $TOOLS_LIBRARY_PATH
我可以使用一个 Package 程序来设置这个环境变量,或者我可以在我自己的路径中设置它。也许有更好的方法来组织一个bash
工具集,但问题是:
我可以信任我的环境变量吗?
这是一个我从来没有真正想过的问题。当用其他语言编程时,路径被用来查找库,(例如LD_LIBRARY_PATH
,PYTHONPATH
,PERLLIB
,RUBYLIB
,CLASSPATH
,NODE_PATH
),但我从来没有停下来想一想这是不安全的。
事实上,LD_LIBRARY_PATH
有Why LD_LIBRARY_PATH
is bad来阻止它的使用。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, functions and security. Bash scripting best practices.。 - Perl的污染模式将所有环境变量都视为“污染的”,这是一个不祥的预兆,这就是为什么我试图对环境的风险进行推理。
- 一个用户不可能更改另一个用户的环境,除非该用户是root用户。因此,我只关心用户更改自己的环境以提升权限。请参阅:Is there a way to change another process's environment variables?
我已经把这个rubber ducked成了一个答案,但我还是要把它贴出来,因为它不是一个现成的答案。
更新:使用环境变量指定库和可执行文件的路径时存在哪些安全问题?
3条答案
按热度按时间gjmwrych1#
虽然各种程序中都存在防止修改环境变量的机制,但底线是,不,您不能信任环境变量。安全问题是非常基本的:
举例来说,请看CVE-2010-3847。有了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,您可能需要考虑启用“paranian”和“strict”选项,以阻止即使是root用户也信任非root用户拥有的二进制文件。
我应该提到这个Trusted Path Execution方法可以保护二进制文件和共享库的直接执行。它对解释语言的作用很小(如果有的话),因为它们解析字节码,而不是直接执行它。所以你仍然需要对
PYTHONPATH
,PERLLIB
,CLASSPATH
等保持一定程度的谨慎,并使用你提到的语言的安全机制。ojsjcaue2#
简短回答:
假设用户能够运行她自己选择的程序和代码,你不必信任他们提供给你的任何东西,包括环境。如果帐户在某些方面受到限制(没有shell访问权,没有对允许执行的文件系统的写访问权),这可能会改变情况,但只要你的脚本只做用户自己可以做的事情,为什么要防止恶意干扰呢?
更长的回答:
就安全问题而言,至少有两个单独的问题需要考虑:
如果且只要程序是在启动程序并提供所有输入的用户的用户ID下运行(即,唯一可以发动任何攻击的人),只有在极少数情况下才有必要加强程序以抵御攻击。反复制保护和共享高分会出现在脑海中,但这组事情不仅仅与输入有关,但在阻止用户阅读代码和内存方面可能更是如此。我不知道如何隐藏shell脚本的代码而不使用suid/sgid技巧;我能想到的最好的办法就是模糊代码。
在这种情况下,用户可以欺骗程序去做的任何事情,他们也可以在没有工具的帮助下去做,所以试图“保护”免受这个用户的攻击是没有意义的。你的描述读起来不像你真的需要任何保护来抵御攻击。
假设您确实需要保护,那么您就不能完全依赖环境变量-如果您无法重置
LD_LIBRARY_PATH
和LD_PRELOAD
之类的内容,即使调用具有绝对路径的工具(如/bin/id
或/bin/ls
)也不会给予可靠的答案,这就是为什么sudo
默认启用env_reset
,以及为什么运行suid程序必须忽略某些环境变量的原因。请注意,这意味着您认为TOOLS_PATH_LIBRARY
和PATH
同样值得信任的观点在您的情况下可能是正确的,但在其他情况的边界情况下不一定是正确的:系统管理员可以重置PATH
,以用于sudo
用途,但是允许非标准环境变量通过。正如上面指出的,
argv[0]
(或者它的bash等价物${BASH_SOURCE[0]}
)并不比环境变量更可靠。execve
或bash的exec -a foo bar
允许将任何内容放入argv[0]
。qvtsj1bj3#
你永远不能相信别人的环境。
为什么不简单地创建一个包含所有这些重要代码的新用户呢?然后,您可以直接从
/etc/passwd
获取信息,或者使用~foo
语法查找用户的主目录。