具有setuid二进制的LD_PRELOAD

时间:2012-02-10 18:32:34

标签: linux setuid ld-preload

我正在尝试使用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.

我尝试使用setuid权限将库放在/usr/lib/usr/local/lib/usr/lib64中,如上所述,但它似乎仍然无效。如果我在标准dirs中使用setuid的情况下我没有给LD_PRELOAD一个路径,那么它似乎无法找到该库。如果我给它路径,它什么都不做。

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)

5 个答案:

答案 0 :(得分:10)

LD_PRELOAD不能与setuid一起使用。这是linux中的一个安全功能。 有关参考检查this article,其中详细介绍了如何使用LD_PRELOAD替换某些库调用替换自定义代码,以malloc为例。

答案 1 :(得分:3)

如果您使用SELinux,可能是因为它。 glibc支持的ELF辅助向量之一是AT_SECURE。此特定参数(默认情况下为0或1)告诉ELF动态链接器取消设置被认为对您的系统有潜在危害的各种环境变量。其中之一是LD_PRELOAD。通常,这种环境卫生是在调用setuid / setgid应用程序时完成的(以防止明显的漏洞)。 SELinux还会在应用程序触发SELinux中的域转换(通过标记为sysadm_t的二进制文件中的mozilla_tmoz或其他任何内容)时增强此卫生条件; SELinux为加载的应用程序设置AT_SECURE标志(在示例中为mozilla / firefox)。

noatsecure权限会禁用特定转换的环境卫生活动。您可以通过以下allow语句执行此操作(因为它将应用于上面的示例):

allow sysadm_t mozilla_t:process { noatsecure };

答案 2 :(得分:0)

在具有glibc的系统上,您可以使用另一种受支持的方式预加载库:将库添加到private func getWalletFromMnemonic(mnemonic: String) -> Dictionary<String, String>? { let PRIVATE_KEY = "privateKey" let ADDRESS = "address" guard let jsContext = self.initialiseJS(jsFileName: "ether") else { return nil } guard let etherObject = jsContext.objectForKeyedSubscript("ethers") else { return nil } guard let walletObject = etherObject.objectForKeyedSubscript("Wallet") else { return nil } guard let walletFromMnemonicObject = walletObject.objectForKeyedSubscript("fromMnemonic") else { return nil } guard let wallet = walletFromMnemonicObject.call(withArguments: [mnemonic]) else { return nil } guard let privateKey = wallet.forProperty(PRIVATE_KEY)?.toString() else { return nil } guard let address = wallet.forProperty(ADDRESS)?.toString() else { return nil } var walletDictionary = Dictionary<String, String>() walletDictionary[ADDRESS] = address walletDictionary[PRIVATE_KEY] = privateKey return walletDictionary } private func initialiseJS(jsFileName: String) -> JSContext? { let jsContext = JSContext() guard let jsSourcePath = Bundle.main.path(forResource: jsFileName, ofType: "js") else { return nil } do { let jsSourceContents = try String(contentsOfFile: jsSourcePath) jsContext!.evaluateScript(jsSourceContents) return jsContext! } catch { print(error.localizedDescription) } return nil } 中。此人不受/etc/ld.so.preload的限制。

特别是,通过这种方式,我可以将LD_PRELOAD预加载(毫无用处,只是为了证明它是有效的),并且在我运行libgtk3-nocsd.so时,库确实显示了/usr/bin/passwd等待当前密码输入时在passwd ruslan中打开。

一个缺点是您无法像使用/proc/<PID_OF_PASSWD>/maps那样在每个应用程序上执行此操作。如果确实需要这样做,也许您可​​以更改库,以尝试根据当前进程二进制文件的路径来检查它是否想要做任何事情(像讨论的here那样检测它)。

答案 3 :(得分:0)

LD_PRELOAD不能与set-user-ID / set-group-ID程序一起使用,除了et-user-ID / set-group-ID程序与相同真实有效的用户和组。

例如,在fork之后和exec*之前,设置

  • setreuid授予设置用户ID程序的所有者
  • setregid到set-group-ID程序的组

答案 4 :(得分:-1)

安装你的lib:

  • location:/ lib或/ usr / lib
  • 权限:root:root
  • 上设置了setuid和setgid

确保将LD_PRELOAD导出到您的环境

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

然后运行你的程序。