每次登录服务器时的 LD_PRELOAD
Posted
技术标签:
【中文标题】每次登录服务器时的 LD_PRELOAD【英文标题】:LD_PRELOAD in every log in to server 【发布时间】:2018-06-01 15:29:44 【问题描述】:我需要在 Linux 中记录所有终端命令。
我在 C 中找到了正确工作的库,但它仅在我运行 LD_PRELOAD=/usr/local/bin/bashpreload.so /bin/bash
时才有效:
# ldd /bin/bash
linux-vdso.so.1 => (0x00007ffef59f8000)
/usr/local/bin/bashpreload.so (0x00007fe691323000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007fe691102000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fe690efe000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe690b6a000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe691524000)
如果我在此之后再次登录系统,我将看不到带有 ldd 的库:
[root@XXX ~]# LD_PRELOAD=/usr/local/bin/bashpreload.so /bin/bash
[root@XXX ~]# ldd /bin/bash
linux-vdso.so.1 => (0x00007ffe481f6000)
/usr/local/bin/bashpreload.so (0x00007f3f1b808000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f3f1b5e7000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f3f1b3e3000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3f1b04f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3f1ba09000)
[root@XXX ~]# exit
[root@XXX ~]# logout
Connection to XXX closed.
[sahaquiel@sahaquiel-PC ~]$ ssh root@XXX
root@XXX's password:
Last login: Tue Dec 19 11:28:22 2017 from YYY
[root@XXX ~]# ldd /bin/bash
linux-vdso.so.1 => (0x00007ffca2f98000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f19a13ff000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f19a11fb000)
libc.so.6 => /lib64/libc.so.6 (0x00007f19a0e67000)
/lib64/ld-linux-x86-64.so.2 (0x00007f19a1620000)
还有一个麻烦:如果我使用这个库,我当前的 PID 正在改变:
Last login: Tue Dec 19 11:28:54 2017 from YYY
[root@XXX ~]# echo "Library is not uploaded"
Library is not uploaded
[root@XXX ~]# echo $$
4639
[root@XXX ~]# LD_PRELOAD=/usr/local/bin/bashpreload.so /bin/bash
[root@XXX ~]# echo $$
4654
[root@212-24-57-104 ~]# ps awwufx | grep -B5 [4]654
root 1706 0.0 0.0 66256 1192 ? Ss 10:54 0:00 /usr/sbin/sshd
root 4517 0.0 0.0 104636 4644 ? Ss 11:27 0:00 \_ sshd: root@pts/1
root 4519 0.0 0.0 108320 1872 pts/1 Ss+ 11:27 0:00 | \_ -bash
root 4637 0.0 0.0 104636 4624 ? Ss 11:30 0:00 \_ sshd: root@pts/0
root 4639 0.0 0.0 108320 1872 pts/0 Ss 11:30 0:00 | \_ -bash
root 4654 0.0 0.0 110376 1956 pts/0 S 11:31 0:00 | \_ /bin/bash
所以,我需要两件事:
-
为每个登录用户找到
LD_PRELOAD
的方法;
知道为什么在此之后我在子/bin/bash
进程中工作。
谢谢!
【问题讨论】:
Stack Overflow 是一个编程和开发问题的网站。这个问题似乎离题了,因为它与编程或开发无关。请参阅帮助中心的What topics can I ask about here。也许Super User 或Unix & Linux Stack Exchange 会是一个更好的提问地点。 【参考方案1】:这是经典的XY problem。您需要记录用户操作、确定解决方案并就该解决方案提出问题。
即使解决方案不起作用。
因为使用LD_PRELOAD
库不是记录用户命令的可靠方式。
-
用户只需取消设置 LD_PRELOAD 环境变量即可。不,marking it
readonly
doesn't work。因为它只是用户控制的进程内存中的一个变量。
您将 LD_PRELOAD
设置为 64 位共享对象。现在每个 32 位程序都将无法运行。
无论您的预加载库如何记录数据,它都是根据用户的权限/访问权限来记录的。因此,用户可以伪造记录的数据。
如果您需要记录用户的操作,请使用旨在安全地执行此操作的系统:auditing。
【讨论】:
审核不是我案例的最佳解决方案,我今天正在探索替代方案。感谢您的建议,32 位程序失败的原因对我来说至关重要。 “您将 LD_PRELOAD 设置为 64 位共享对象。现在每个 32 位程序都将无法运行”不是真的。如果 ELF 类不同,它将被简单地忽略;除了诊断消息之外,不会发生任何不愉快的事情,并且 32 位程序仍然可以正常运行。 @usr 如果 ELF 类不同,它将被简单地忽略 错误。试试file /usr/bin/bash
。你会看到/usr/bin/bash: ELF 64-bit LSB...
。然后export LD_PRELOAD=/lib/libc.so
,一个32 位 共享对象。之后,输入/usr/bin/bash
以尝试运行bash
的另一个副本。你得到ld.so.1: bash: fatal: wrong ELF class: ELFCLASS32
,因为LD_PRELOAD
指定要加载的32位共享对象是错误的。
@AndrewHenle 如您所说,使用 32 位库会产生“错误:ld.so:无法预加载来自 LD_PRELOAD 的对象'/lib/i386-linux-gnu/libc.so.6'(错误的 ELF 类:ELFCLASS32):被忽略。”。就像我说的那样,它被忽略了(/lib/i386-linux-gnu/libc.so.6 是我系统上的 32 位 libc)。【参考方案2】:
想办法为每个登录用户安静地执行 LD_PRELOAD
您需要为所有用户设置一个共同的位置,例如/etc/profile
或/etc/environment
。
有关更多选项/详细信息,请参阅How to set environment variable for everyone under my linux system?。
知道为什么在此之后我在子 /bin/bash 进程中工作。
这很简单——每当你创建一个进程时,它的 PID 就不同于它的父进程 :) 当你运行 /bin/bash
时,你显然会创建另一个 shell,这就是 $$
不同的原因。这与LD_PRELOAD
无关。如果您在没有LD_PRELOAD
的情况下运行/bin/bash
,您将观察到完全相同的行为。
【讨论】:
谢谢,我还是不太明白 LD_PRELOAD 是如何工作的,需要多读。 /etc/profile 的解决方案听起来不错,但你能解释一下,如何在 shell-script 中执行库添加?添加LD_PRELOAD /usr/local/bin/mylib.so /bin/bash
就足够了吗? UPD。它不起作用:(我不能使用export
,因为我需要这个库只用于/bin/bash
LD_PRELOAD=/usr/local/bin/bashpreload.so
是您在 /etc/profile 中设置的方式。但要非常小心 - 根据 LD_PRELOAD 库的作用,这可能会严重影响用户,并且可能是一个安全漏洞。有关 shell 特定选项,请参阅 unix.stackexchange.com/q/117467/192153。如果您只希望它用于 bash,您可以查看 bashrc
文件。【参考方案3】:
如果有人和我一样需要:
您可以在用户通过 SSH 登录之前在/etc/security/pam_env.conf
中添加环境变量,语法如下:
LD_PRELOAD DEFAULT= OVERRIDE="/usr/local/bin/bashpreload.so"
【讨论】:
以上是关于每次登录服务器时的 LD_PRELOAD的主要内容,如果未能解决你的问题,请参考以下文章