使用 LD_PRELOAD 与 setuid 二进制文件

11

我试图使用LD_PRELOAD在具有setuid权限的应用程序中预加载库。起初尝试了LD_PRELOAD,但似乎被setuid二进制文件忽略了,尽管在尝试其他像lsdir等命令时,它是有效的。

根据LD_PRELOAD的文档:

   LD_PRELOAD
          A whitespace-separated list of additional, user-specified, ELF shared
          libraries to be loaded before all others.  This can be used to
          selectively override functions in other shared libraries.  For set-
          user-ID/set-group-ID ELF binaries, only libraries in the standard
          search directories that are also set-user-ID will be loaded.

我尝试按照上面这份文档的指示,将该库放置在 /usr/lib/usr/local/lib/usr/lib64 目录下,并且使用 setuid 权限,但似乎仍然不起作用。如果我没有在 LD_PRELOAD 中给出路径,在标准目录中使用 setuid 权限放置该库,则无法找到该库。如果我给它提供路径,则没有任何作用。

setuid 二进制文件是一个在非 root 用户 shell 中运行的具有 root 权限的二进制文件。有什么想法吗?不确定是否漏掉了路径、环境变量或者我误解了上面的文档。

编辑:根据要求的权限:

库:

-rwsr-sr-x 1 root root 72580 2012-02-10 07:51

应用程序:

-rwsr-xr-x 1 root root 137517601 2012-02-10 

env | grep LD
LD_LIBRARY_PATH=/usr/lib (I added this manually myself, usually LD_LIBRARY_PATH is empty)

你是否正在运行SELinux? - Michael Foukarakis
是的,我目前正在运行Suse企业11.1。 - Mark Lobo
3
终于成功了,在所有的测试中,我一定弄错了什么。将它放在lib64中,并设置正确的权限(setuid),而不提供LD_PRELOAD的路径是可行的。感谢大家的帮助! - Mark Lobo
5个回答

15

LD_PRELOAD不能与setuid一起使用。这是Linux中的一种安全特性。 有关详细信息,请参见此文章,该文章详细介绍了如何使用LD_PRELOAD来用自定义代码替换某些库调用,以malloc为例。


5
如果您正在使用SELinux,这可能是由于它导致的。glibc支持的ELF辅助向量之一是AT_SECURE。这个特定的参数(默认为0或1)告诉ELF动态链接器取消各种被认为对系统有潜在危害的环境变量。其中一个是LD_PRELOAD。通常,在调用setuid/setgid应用程序时执行此环境清理操作(以防止明显的漏洞)。SELinux还增强了此清理操作,使其在应用程序触发SELinux中的域转换时(例如通过标记为moz的二进制文件从sysadm_tmozilla_t),SELinux为加载的应用程序(在此示例中为mozilla/firefox)设置AT_SECURE标志。 noatsecure权限禁用特定转换的环境清理活动。您可以通过以下允许语句来实现此目的(如上面的示例所示):
allow sysadm_t mozilla_t:process { noatsecure };

SELinux是安全增强的Linux还是SUSE企业版?我正在运行后者。您提到的内容对SUSE企业版仍然适用吗? - Mark Lobo
根据此链接,SELinux是SUSE Enterprise 11.1版本中的一个选项。然而,如果您没有使用它,我的回答就不适用了。 - Michael Foukarakis
从我所看到的,我没有运行Selinux。我没有看到任何通常的selinux配置选项。我确实看到了AppArmour,但它也被禁用了。 - Mark Lobo

0

在使用glibc的系统上,您可以使用另一种支持的方式预加载库:将库添加到/etc/ld.so.preload中。这种方式不会受到LD_PRELOAD的限制。

特别是,我能够将libgtk3-nocsd.so无用地预加载到/usr/bin/passwd中,并且当我运行passwd ruslan时,该库确实出现在/proc/<PID_OF_PASSWD>/maps中,而passwd正在等待当前密码输入。

一个缺点是您不能像使用LD_PRELOAD那样对每个应用程序进行操作。如果您真的需要这样做,也许您可以更改库以尝试检查它是否想要执行任何操作,基于当前进程二进制文件的路径(像这里所讨论的那样进行检测)。


0

LD_PRELOAD 不能与 set-user-ID/set-group-ID 程序一起使用,除非 et-user-ID/set-group-ID 程序正在以相同的真实用户和组运行。

例如,在 forkexec* 之后,设置

  • setreuid 为 set-user-ID 程序的所有者
  • setregid 为 set-group-ID 程序的组

-1

按照以下方式安装您的库:

  • 位置:/lib 或 /usr/lib
  • 权限:root:root
  • 已启用 setuid 和 setgid

确保将 LD_PRELOAD 导出到您的环境中

$ export LD_PRELOAD=/usr/lib/yourlib.so
$ env | grep LD_PRELOAD  # verify

然后运行你的程序。


它不起作用,并且将库应用于_所有_应用程序。我试图使用LD_PRELOAD=... appname来仅为此应用程序预加载它。作为一个实验,我将ls复制到自己的目录中,并添加了setuid权限(chmod u+s ./ls)。我的库以前可以与ls一起工作,但是现在无法与此本地权限更改的库一起工作。:( 作为另一个实验,我尝试将lib添加到/etc/ld.so.preload中,它可以工作,但是再次适用于所有应用程序。如果可能的话,我希望它能够与LD_PRELOAD=.. appname一起工作。 - Mark Lobo
你能否编辑并显示出ls -lad命令在你的lib和程序上的结果,以及env | grep LD命令的结果? - Christopher Neylan
已添加编辑。感谢您的帮助!只需要再澄清一下,当我将它放在/etc/ld.so.preload中时,我的应用程序似乎也可以使用该库,但它适用于所有应用程序。也许LD_PRELOAD的一些检查在ld.so.preload情况下被跳过了。此外,当我以root身份运行sudo并运行时,LD_PRELOAD可以与我的应用程序一起使用,但不幸的是我不能作为root运行该应用程序。这只是一个快速实验。 - Mark Lobo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接