据观察,当运行设置了 setuid 位的程序时,它不会接收 shell 上设置的某些环境变量(bash 等)。通过这种方式删除的几个环境变量是LD_PRELOAD, LD_LIBRARY_PATH, LD_ORIGIN_PATH, LD_DEBUG_OUTPUT, LD_PROFILE, LD_USE_LOAD_BIAS, GCONV_PATH
。
正如中提到的这里并在这个问题,这是预期的行为。这样做的原因是为了减少攻击向量。的手册页ld.so (8)
也说明了这一点。
问题是,Linux 操作系统的哪个组件会像这样删除环境变量?
- 是壳吗?
- 它是shell 在执行命令时内部调用的函数吗
fork()
?execve()
- 是吗
ld.so
?
注意:任何答案都会有帮助。但是,如果您可以指导我哪些资源包含有关此问题的信息,例如我应该阅读哪些手册页,那就会更有帮助。
答案1
这些变量中的大多数用于动态链接器或 C 库的其他组件,动态链接器负责在启动 setuid 二进制文件时删除它们。这记录在的“环境”部分man ld.so
(针对 GNU C 库):
出于安全原因,如果动态链接器确定应在安全执行模式下运行二进制文件,则某些环境变量的作用将被无效或修改,并且这些环境变量将从环境中剥离,从而程序甚至不会执行任何操作。请参阅定义。其中一些环境变量会影响动态链接器本身的操作,如下所述。以这种方式处理的其他环境变量包括:
GCONV_PATH
、GETCONF_DIR
、HOSTALIASES
、LOCALDOMAIN
、LOCPATH
、MALLOC_TRACE
、NIS_PATH
、NLSPATH
、RESOLV_HOST_CONF
、RES_OPTIONS
、TMPDIR
和TZDIR
。
影响ld.so
变量单独记录:
在安全执行模式下该变量被忽略。
出现在每个此类变量的文档中。
完整名单也可见在 GNU C 库的源代码中,删除代码本身也可以,两者对于动态链接的二进制文件和用于静态链接二进制文件中的动态链接。
其他 C 库的动态链接器对于它们关心的变量以类似的方式运行;例如,musl 文件表明
在调用 setuid、setgid 或其他提升功能的程序中,该变量被完全忽略。
对于许多变量(LD_PRELOAD
、LD_LIBRARY_PATH
、MUSL_LOCPATH
),并且TZ
变量的某些功能在这种情况下不可用。