最近在搞CTF的出题,就看到了《红蓝对抗中的云原生漏洞挖掘及利用实录》中关于Serverless 实战能挖到的漏洞的总结,这里就复制粘贴出来,作为记录。
本文提到了一种可能导致命令执行的漏洞,即文件驻留导致命令执行。开发者在清理用户文件时可能会出现问题,从而导致多个用户在同一容器环境下运行,难以保证安全性。本文通过一个具体的例子来说明这个问题,同时也提供了一些解决思路。需要注意的是,由于Serverless容器环境的信息相对单一和简便,因此容器环境里值得我们探索和翻找的地方不多。
文件驻留导致命令执行
有些Serverless实现在应用程序生命周期结束之后,程序文件的清理上进入了僵局。一方面开发者希望借助容器“对Linux Cgroup和Namespace进行管理的特性”用于实现限制应用的资源访问能力和进程权限的需求;在此之上,开发者希望能更快的达到用户文件清理的目的,避免反复初始化容器环境带来的时间和资源上的消耗,复用同一个容器环境。
而在蓝军的视角里,这样的处理方式会导致多个用户的应用会存在多个用户在不同时间段使用一个容器环境的情况,在安全性上是比较难得到保障的。
以面向Python开发者的Serverless架构为例,开发者所构想的简化模型是这样的:
用户文件清理的代码实现上,简化可参考:
在进行包括上述文件删除动作在内的一系列环境清理工作之后,容器内外的主调度进程会写入其他租户的代码到当前容器内,此时这个容器就进入了下一个应用的Serverless生命周期。
虽然,主框架代码实现内有很多类似调用系统命令拼接目录等参数进行执行的代码实现,但是类似命令注入的问题大多只能影响到当前的生命周期;而又因为用户权限的问题,我们没办法修改其他目录下的文件。
于是我们构建了这样一个目录和文件:
当程序执行 rm -rf 时,因为 bash glob 对 号的返回是有默认排序的,这里可参考下方 bash 的文档,只要我们不去修改 LC_ALL 的环境变量,我们构造的 —help 文件会排列在文件列表的最前方,导致 rm 会执行 rm —help 而终止,恶意文件得以保留。
Pathname Expansion
After word splitting, unless the -f option has been set, bash scans each word for the characters , ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern.*
我们可以简单在 bash 内进行验证,可以看到 rm -rf * 命令被 —help 强行终止,我们所植入的恶意文件还依然存在没有被清理掉,同时 rm —help 的命令执行返回为 0,不会产生 OS ERROE Code,清理进程会认为这里的清除命令已经成功执行:
而实际在serverless log里的返回,可参考:
此时,serverless的主调度程序会以为自己已经正常清理了容器环境,并写入另外一个租户的源码包进行执行,而当另外一个租户的代码执行至 import requests 时,我们驻留在应用目录下的 requests.py 内的恶意代码就会被执行。
不过值得注意的是,因为 serverless 的生命周期一般极为有限,所以此时获取的shell可能会在短时间结束,触发新一轮的反弹shell,且Servless容器环境内的信息相对单一和简便。所以容器环境里值得我们探索和翻找的地方也不多,一般需要关注:]
- 新的代码
- 代码内部配置
- 环境变量
- 秘钥、证书、密码信息等
不同的serverless架构实现对于存储和传递相应信息的方式各有不同。
攻击公用容器/镜像
现在我们知道了,很多Serverless的用户代码都跑在一个个容器内。不同应用的代码运行于不同的容器之上,依靠容器原本的能力进行资源回收和隔离。由于Serverless应用的代码会进行相应的结构化解耦,且每个应用容器的底层环境相对来说是一致的。所以其实,根据应用漏洞获取更多应用类Serverless容器不仅困难而且在内网渗透中作用相对较为有限,能做的事情也相对较少。
但其实在不同的 Serverless 架构中,都有多类持久化且公用的容器以实现程序调度、代码预编译、代码下载运行等逻辑。
这类容器一般拥有获取所有用户代码、配置和环境变量的能力,同时也比较容易出现 Docker IN Docker或大权限 Service Account的设计。
如何控制这类型的容器呢?以下是我们在攻防过程中遇到的场景:
1、在下载源代码时,使用 git clone 进行命令拼接,导致存在命令注入;
2、在安装 node.js 依赖包时,构造特殊的 package.json 利用 preinstall 控制公用容器。
3、配置指向恶意第三方仓库的 pip requirements.txt,利用恶意 pip 包获取依赖打包容器的权限,同类的利用手法还可以作用于nodejs、ruby等语言的包管理器。
4、因为容器镜像里的打了低版本git、go等程序,在执行 git clone, git submodule update(CVE-2019-19604), go get 时所导致的命令执行,下图为 CVE-2018-6574 的 POC 可参考:https://github.com/neargle/CVE-2018-6574-POC/blob/master/main.go。
原文始发于微信公众号(黑伞安全):Serverless 漏洞挖掘-SRC真的能遇到
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论