执行前验证命令二进制文件


13

有什么方法可以检查您从bash脚本实际执行的操作吗?

说你的bash脚本调用几个命令(例如:tarmailscpmysqldump),你愿意以确保tar是真正的,真实的tar,这是由确定root用户是该文件的父目录的所有者,也是唯一一个具有写权限而不是/tmp/surprise/tar拥有者www-dataapache2拥有者。

当然,我知道PATH环境,我很想知道是否可以从正在运行的bash脚本中另外检查一下,如果可以的话,如何检查?

示例:(伪代码)

tarfile=$(which tar)
isroot=$(ls -l "$tarfile") | grep "root root"
#and so on...

2
如果您如此偏执,请使用自己的二进制文件!
Ipor Sircer

8
除了xhienne回答which不正确的说法tar外,ls还可能被黑客返回有关文件的错误信息(如果有)。也grep可能被黑以返回错误信息;可以通过改用Shell匹配来避免这种情况,但随后可能会破坏Shell。首先,可以破解shell来产生错误的结果type-或完全替换掉shell,因为与50年前的OS相比,shell的可替换性是Unix的一项重要创新。参见肯·汤普森(Ken Thompson)1984年的图灵演讲。一直都是乌龟。
dave_thompson_085

2
在Linux上,我无法回答这个问题,只有AIX,它有一个称为Trusted Execution(TE)的组件,它的数据库带有签名(即,比MD5校验和更广泛。当TE处于活动状态并且数据库中有文件时,您可以选择程序是否运行-或仅警告它与数据库不匹配。此外,还有其他两个设置:(TEP可信执行路径)和TLP(可信库路径)。仅可执行TEP中的程序,并且只能使用该目录包含在TLP中。在Linux中,我有一个名为“ AppArmor”的内容可能会对您有所帮助
Michael Felt

1
您可以具有这种安全性,但是不能从脚本中获得安全性-到脚本在不受控制的环境中执行时,为时已晚。就您所知,您所看到的一切都是攻击者设置的chroot。
查尔斯·达菲

2
...如果您想拥有一个一直以来都值得信赖的系统,则需要采用ChromeOS的方法:使用嵌入在硬件中的密钥对固件进行签名;您的引导加载程序/内核已通过固件验证;您的根OS分区是只读的,使用块级签名进行验证;等。还有一些类似于@MichaelFelt讨论的方法-请参阅完整性度量体系结构-但性能影响更高,完整性级别降低(因为检查二进制签名对通过非可执行程序的攻击没有帮助内容)。
查尔斯·达菲

Answers:


24

您可以从头开始执行正确的二进制文件,而不必验证要执行的二进制文件。例如,如果要确保不运行/tmp/surprise/tar,只需/usr/bin/tar在脚本中运行即可。或者,$PATH在运行任何东西之前将您的值设置为合理的值。

如果您不信任/usr/bin/其他系统目录中的文件,则无法恢复信心。在您的示例中,您正在使用来检查所有者ls,但是您如何知道您可以信任ls?相同的论点适用于其他解决方案,例如md5sumstrace

在需要高度信任系统完整性的地方,可使用IMA等专用解决方案。但这不是您可以在脚本中使用的东西:整个系统必须以一种特殊的方式来设置,并具有不可变文件的概念。


当不同的发行版选择放置二进制文件/bin而不是时,这会中断/usr/bin
Damian Yerrick

IMA是两种可用于生产环境的方法之一,另一种是ChromeOS用来对rootfs进行块级验证的dm-verity方法。
Charles Duffy

@DamianYerrick博览会言论。$PATH如果需要多个分发支持,则设置为这两个路径。
德米特里·格里戈里耶夫

AIX TE(带有或不带有RBAC)将是第三个“生产就绪”内核内置的内核,可以完成此任务-也许更多。一旦启用,TE不仅可以被动使用-将阻止打开文件和/或执行程序。此外,可以将应用程序和库的使用设置为仅在TEP(可信执行路径)或TLP(可信库路径)上。见ibm.com/support/knowledgecenter/en/ssw_aix_61/...基本信息
迈克尔毛毡

6

如果入侵者已经获得了对系统的访问权限并且能够修改您的系统$PATH/tmp在任何情况下都不应包括在内),那么现在开始担心可执行文件的所有权就为时已晚。

相反,您应该阅读有关如何处理入侵的信息

最好集中精力完全避免入侵。

如果您的系统会影响这类事情,那么最好将需要公开的部分与需要私有的部分隔离开来,并对通信模式进行审核在这些之间。


4

可以通过验证md5sum文件的某种程度。因此,在使用apt包管理的系统上(在我的特例中是Ubuntu 16.04),存在一个文件/var/lib/dpkg/info/tar.md5sums,该文件存储tar安装期间来自所有文件的md5总和。因此,您可以编写一个简单的if语句,检查语句的输出是否md5sum /bin/tar与该文件中的内容匹配。

那当然是假设文件本身没有被篡改。当然,只有在攻击者获得root / sudo访问权限时(此时所有赌注都已关闭),才会发生这种情况。


8
但是,您如何验证/usr/bin/md5sum
德米特里·格里戈里耶夫

如果攻击者能够替换/bin/tar/usr/bin/tar,则可能他们也可以简单地替换md5sum/var/lib/dpkg/info/tar.md5sums。或者$SHELL
乔纳斯·谢弗(JonasSchäfer)

1
我想我已经在上一段中提到过,要使这种事情发生,攻击者将需要获得对系统的root访问权,到那时一切皆有可能。在某些情况下,攻击者没有root访问权,但可以为用户更改PATH变量或创建一个别名,该别名tar指向其他二进制文件,它将起作用。当系统在根目录上遭到入侵时,您有一个选择,然后-从轨道上对其进行核弹
Sergiy Kolodyazhnyy

3

是的,有一种方法:内置type。与which仅在PATH中搜索的命令相反,type它将告诉您命令名称实际上是保留关键字,内置关键字,别名,函数还是磁盘文件。

$ type -t foobar || echo "Not found"
Not found

$ type -t echo
builtin

$ enable -n echo; type -t echo; type -p echo
file
/usr/bin/echo

$ echo() { printf "(echoing) %s\n" "$*"; }; type -t echo
function

$ alias echo="/bin/echo 'I say: ' "; type -t echo
alias

此外,type -a还会为您提供命令的所有候选项(从第一个到最后一个选择):

$ type -a echo
echo is aliased to `/bin/echo 'I say: ' '
echo is a function
echo () 
{ 
    printf "(echoing) %s\n" "$*"
}
echo is a shell builtin
echo is /usr/local/bin/echo
echo is /bin/echo

最后,如果您只关心磁盘上的二进制文件,则可以使用type -Pa来获取PATH中的所有二进制文件(与上述顺序相同):

$ type -Pa tar
/home/me/bin/tar                <= oh oh, is this normal?
/bin/tar

就是说,type仅靠一句话并不能告诉您到底将调用什么命令。例如,如果您tar是调用二进制文件的别名(例如alias tar="/tmp/tar"),type则将告诉您这是一个alias


type -a包括所有形式(例如别名和外部程序)
dave_thompson_085

谢谢@dave,的确很有趣,我已经更新了答案
xhienne

1
type会在bash知道的范围内告诉您,但是如果我们受到恶意攻击者的控制,则没有理由相信bash认为知道的内容反映了真实情况。众所周知,有一个LD_PRELOAD模块可以拦截您进行的每个C库调用。
Charles Duffy

1
@CharlesDuffy您当然是正确的。我不想从安全角度回答。我只是在顶部提出一个问题的答案:“是否有任何方法可以检查您从bash脚本实际执行的内容”,并提出了的替代方法which
xhienne

我从未见过enable。我使用了这些答案中的建议type enable来找出它是内置的shell,然后help enable查看它的作用。

3

您可以使用来检查脚本确切执行了哪些命令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是多线程的,则将附加进程PID的所有线程,而不仅限于thread_id = PID的线程。

-e trace=file:跟踪所有以文件名作为参数的系统调用。您可以将其视为缩写,-e trace=open,stat,chmod,unlink,...这对于查看进程所引用的文件很有用。此外,使用缩写将确保您不会意外忘记在列表中包括lstat之类的调用。


3
脚本不能通过任何方式来执行自动化测试,也没有特别的理由相信它strace本身并没有被颠覆。
Charles Duffy

0

Linux os基于文件,并且在linux上执行的许多命令可能会解决您计算机上文件中的某些更改。因此,这也许是解决您问题的最佳解决方案。您可以在文件系统上执行任何命令之前对其命令进行测试。

在此处输入图片说明

有'strace'命令可以部分分解您的命令...

在此处输入图片说明

如果您真的想深入了解,请检查反编译器以了解将要执行的脚本。换句话说,您必须检查该命令的汇编程序解释。在那里狂欢objdump -d。Linux bin脚本主要使用C编程语言创建,因此请使用良好的C反编译器。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.