有什么方法可以检查 bash 脚本实际执行的内容吗?
假设您的 bash 脚本正在调用多个命令(例如:tar
、mail
、scp
、mysqldump
),并且您愿意确保这tar
是实际的、真实的tar
,这可以由root
作为文件和父目录所有者的用户以及唯一具有写入权限的用户来确定而不是一些/tmp/surprise/tar
拥有者www-data
或apache2
拥有者。
当然我了解PATH
环境,我很好奇这是否可以另外检查了来自正在运行的 bash 脚本,如果是这样,具体是怎样的?
示例:(伪代码)
tarfile=$(which tar)
isroot=$(ls -l "$tarfile") | grep "root root"
#and so on...
答案1
您可以从一开始就执行正确的二进制文件,而不是验证要执行的二进制文件。例如,如果您想确保不会运行,只需在脚本中/tmp/surprise/tar
运行即可。/usr/bin/tar
或者,$PATH
在运行任何操作之前将您设置为一个合理的值。
如果您不信任系统目录/usr/bin/
和其他系统目录中的文件,则无法重新获得信心。在您的示例中,您正在使用 来检查所有者ls
,但是您如何知道您可以信任呢ls
?同样的论点也适用于其他解决方案,例如md5sum
和strace
。
如果需要对系统完整性抱有高度信心,可以采用专门的解决方案,例如我是一个被使用。但这不是您可以从脚本中使用的东西:整个系统必须以特殊的方式设置,并采用不可变文件的概念。
答案2
如果入侵者已获得对您的系统的访问权限并能够修改您的系统$PATH
(在任何情况下都不应包括在内/tmp
),那么开始担心可执行文件的所有权就为时已晚。
相反,你应该阅读有关如何应对入侵。
最好集中精力完全避免入侵。
如果您有一个系统,这些事情很重要,那么最好将需要公开的部分与需要私有的部分隔离开来,并对通信模式进行审核这些之间。
答案3
在某种程度上可以通过验证md5sum
文件来实现。因此,在使用包管理的系统上apt
- 在我的特定情况下,Ubuntu 16.04 - 有一个文件/var/lib/dpkg/info/tar.md5sums
,它存储安装过程中来自的所有文件的 md5 和tar
。因此,您可以编写一个简单的 if 语句来检查 的输出是否与md5sum /bin/tar
该文件中的内容匹配。
当然,这是假设文件本身没有被篡改。当然,只有当攻击者获得 root/sudo 访问权限时才会发生这种情况,此时所有的赌注都会被取消。
答案4
您可以使用 来检查脚本正在执行哪些命令strace
。例如:
strace -f -e execve ./script.sh
使用以下脚本:
#!/bin/bash
touch testfile.txt
echo "Hello" >> testfile.txt
cat testfile.txt
rm testfile.txt
strace
-e execve
将告诉您与参数一起使用时执行的命令的确切路径:
execve("./script.sh", ["./script.sh"], [/* 69 vars */]) = 0
Process 8524 attached
[pid 8524] execve("/usr/bin/touch", ["touch", "testfile.txt"], [/* 68 vars */]) = 0
[pid 8524] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8524, si_status=0, si_utime=0, si_stime=0} ---
Process 8525 attached [pid > 8525] execve("/bin/cat", ["cat", "testfile.txt"], [/* 68 vars */]) = 0
Hello [pid 8525] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8525, si_status=0, si_utime=0, si_stime=0} ---
Process 8526 attached [pid > 8526] execve("/bin/rm", ["rm", "testfile.txt"], [/* 68 vars */]) = 0
[pid 8526] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=8526, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
参数(来自 strace man):
-f
:跟踪当前跟踪的进程由于 fork(2)、vfork(2) 和clone(2) 系统调用而创建的子进程。请注意,-p PID -f
如果是多线程,将附加进程 PID 的所有线程,而不仅仅是 thread_id = PID 的线程。
-e trace=file
:跟踪所有以文件名作为参数的系统调用。您可以将其视为缩写,对于-e trace=open,stat,chmod,unlink,...
查看进程正在引用哪些文件很有用。此外,使用缩写将确保您不会意外忘记在列表中包含像 lstat 这样的调用。