我正在尝试使用LD_PRELOAD
来预加载具有setuid权限的应用程序的库。最初尝试LD_PRELOAD
,似乎它被setuid二进制文件忽略了,但是当我尝试与ls
,dir
等其他人一起使用时,它正在工作。
来自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)
答案 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_t
到moz
或其他任何内容)时增强此卫生条件; 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:
确保将LD_PRELOAD导出到您的环境
$ export LD_PRELOAD=/usr/lib/yourlib.so
$ env | grep LD_PRELOAD # verify
然后运行你的程序。