Py学习  »  docker

高度安全环境下的Docker和Kubernetes

Docker • 4 年前 • 508 次点击  

这是笔者研究生论文的部分内容和基于此得出的结论的一个简要总结。本文侧重于探讨容器化应用程序的隔离问题。论文里还介绍了Kubernetes集群网络的部分,这里不做讨论。

你可以在这里找到笔者完整的论文,它是公开可以访问的:http://kth.diva-portal.org/smash/record.jsf?pid=diva2:1231856。

近年来,容器编排和云原生计算获得了许多人的关注。行业内的采用率甚至已经高到金融、银行和国企单位都感兴趣的程度。与其他企业相比,他们在信息安全和IT安全方面有着更为广泛的要求。

其中一个重点在于如何在生产环境中使用容器的同时保持应用程序之间的系统隔离性。由于这类企业以前使用的是由裸金属虚拟化驱动的私有云,迁移到容器编排环境造成的隔离方面的损失不容忽视。这也正是笔者论文研究的范畴,它是以瑞典警察局为目标客户编写的。

论文里具体研究的问题如下:

相比于通过裸金属hypervisor ESXi驱动的虚拟机而言,Docker和Kubernetes是如何实现瑞典警察局应用程序之间的系统隔离?

这个问题有很多需要展开的地方。首先,我们先来看一下它们共同关注的对象 - 应用程序。

混乱的Web应用


Web应用程序里的漏洞就像是攻击者的游乐园,OWASP Top 10(2013[1],2017[2]揭示了这里面最突出的十个安全风险。这类资源有助于引导开发人员规避一些常见的安全风险。然而,即便假设开发人员编写的所有代码都是完美无瑕的,应用程序仍然可能遭受攻击,例如,代码包依赖导致的安全问题。

David Gilbertson[3]撰写了一篇关于如何通过分发恶意软件包(以Node.js应用为例的话就是NPM)来实现代码注入的精彩故事。尽管依赖扫描程序能够用来发现漏洞,但是它只能降低风险,并不能完全消除这一风险。

即便用户构建了一个没有第三方依赖的应用程序,但是想要做到应用程序永远不会受到攻击仍然是不现实的。

由于这些风险的客观存在,我们无法假定Web应用是安全的。

相反,我们必须采取纵深防御策略[4]。那么,让我们一起来看看应用的下一层——容器和虚拟机!

容器与虚拟机——一个关于隔离的故事


容器是一个隔离的用户态环境,一般通过内核的功能来实现。比如,Docker通过Linux namespace,cgroup和capability来达成这一目标。在这方面,相比于通过裸金属hypervisor驱动的虚拟机而言,Docker容器的隔离效果有很大差别

在虚拟机的世界里,隔离可以通过像Intel VT这样的实际硬件实现。另外一方面,Docker容器依赖于Linux内核进行隔离。在考虑底层攻击(layer-below attacks)时,它们之间的这一差异就显得尤为突出。

如果攻击者能够在虚拟机或容器中执行代码,那么攻击者可以通过攻击底层实现逃逸攻击。 

图1 根据使用的是容器还是裸金属虚拟机,隔离的实现层次也各不相同

在Pwn2Own 2017黑客大赛以及GeekPwn2018大会期间,裸金属hypervisor VMware ESXi验证了这类攻击。结果便是爆出了好几个CVE(例如CVE-2017-4902[5],CVE-2018-6981[6]),它们可用于底层攻击以实现虚拟机逃逸。尽管裸金属虚拟机使用的是硬件级别的隔离技术,但是它并不能确保它们是绝对安全可靠的。

另外一方面,如果我们考虑裸金属 hypversior 与 Linux 内核相比,谁的攻击面更广的话,很显然是后者,因为它更为庞大,涉及的功能范围也更广。而更大的攻击面则意味着依赖于容器隔离的云存在更多潜在的攻击目标。这反映在对容器逃逸攻击的日益关注,这类攻击已经通过一些内核漏洞被验证是可行的(例如CVE-2016-5195[7],CVE-2017-1000405[8])。

要提高容器内部的隔离性的话,我们可以使用SELinux或AppArmor等安全模块。不幸的是,这种基于内核的安全机制并不能阻止基于内核的逃逸攻击。即便没有逃脱,它也只会限制攻击者的行为。如果我们想要真正解决容器逃逸攻击问题的话,我们需要在容器外部甚至内核中使用一些隔离机制。比如一个沙盒!

gVisor是一个由Google开源的容器运行时沙盒,它在容器和操作系统内核之间添加了一个额外的内核。这种类型的沙盒可以缓解基于内核的容器逃逸攻击。但是对于攻击者而言,内核漏洞攻击只是工具箱里的其中一个手段而已。

要了解攻击者的其他手段,我们必须站在更高层面看待容器在云原生时代的使用方式。

集装箱编排对隔离的影响


为了管理在多节点环境中运行的容器,我们采用了容器编排系统,其中 Kubernetes 占据主导地位。事实证明,编排器中的错误也会影响容器隔离。

Tim Allclair在KubeCon 2018大会上给我们做了一次精彩的演讲,这里面他着重提到了几个攻击面。在他的演讲中,他提到了一个关于编排错误如何影响隔离的案例(CVE-2017-1002101[9]),在这种情况下,攻击者通过在Pod外部挂载存储卷实现逃逸攻击。这一类型的漏洞很有问题,因为它也可能会绕过包装容器的沙盒。

在引入Kubernetes之后,我们又多了一个被攻击的对象。Kubernetes Master的几个系统服务就是其中之一。一个例子便是Kubernetes APIServer,最近发现存在一个权限提升的漏洞(CVE-2018-1002105[10])。由于 Kubernetes Master 的攻击面超出笔者论文讨论的范畴,这里先不考虑这类特定的漏洞。

那么,为什么说逃逸攻击是一个大问题呢?容器引入了在同一个宿主操作系统上运行多个共址应用程序的能力。这带来了应用程序隔离的风险。如果一个关键业务的应用程序和另一个易受攻击的应用程序运行在同一台宿主机上,那么攻击者可以通过攻击易受攻击的应用程序来获取对关键应用程序的访问权限。

根据企业处理的数据类型的不同,数据泄露可能还会损害除了企业自身以外的个人和国家。别忘了,我们的客户都是一些国企单位、金融、银行等,如果出现异常可能会严重影响人们的生活。

那么,在这样的环境下还能使用容器编排吗?在我们进一步研究这个思路之前,我们需要先做一些风险评估。

什么是可接受的风险?


在介绍一些安全措施之前,反思一下企业想要保护的实际信息到底是什么也很重要。根据企业处理的数据及其提供的服务的不同,可能需要也可能不需要针对容器逃逸攻击采取任何进一步的对策。

正确的说 - 为了在一台使用容器沙盒进行加固过的配置好的主机上实施容器逃逸攻击,攻击者必须:

  1. 例如通过代码注入或使用应用程序代码中的现有漏洞来执行容器中的代码;

  2. 尽管存在容器沙盒,但是可以利用另一个0day或者未修补的漏洞实现容器逃逸。


你懂的,对于上述这些场景,从事数据处理或者是提供对机密性完整性以及/或者是可用性方面要求很高的服务的企业断然是无法接受的。

笔者论文是将这些客户的情况考虑在内的,而容器逃逸造成的系统隔离性的损失显然是无法接受的,因为这样造成的后果非常严重。那么,我们可以采取哪些措施来进一步地提高容器的系统隔离性呢?想要在隔离性上面迈出一步的话,我们不妨考虑一下包装了操作系统内核的沙盒 - 虚拟机!

尽管利用受托管的hypervisor的虚拟化技术可以带来一些提升,但是我们希望能够进一步限制攻击面。因此,让我们利用一下裸金属hypervisor,看看他们能够为我们带来什么。

裸金属hypervisor


在瑞典国防研究局发布的一份报告[11]中,他们对瑞典武装部队使用虚拟化技术的风险进行了评估。报告的结论是,尽管安全性方面存在一些苛刻要求,而且虚拟化可能会带来一些潜在的风险,但是对于武装部队而言引入虚拟化技术仍然是有用的。

在这方面,我们不妨假定我们在国防工业中(在某种程度上)已经使用了虚拟化技术,因为它带来的风险是可以接受的。由于国防工业中的代理商和企业是IT安全领域里要求最苛刻的客户之一,我们也可以说,对他们来说可接受的风险,也是本论文范畴内的其他客户可以接受的。我们之前也讨论过虚拟机逃逸的可能性,它其实也是这样。

如果我们决定将容器搭配这种类型的沙盒一起使用的话,我们还需要将一些因素考虑在内,让它变得更具备云原生的特性。

虚拟机沙盒节点


我们的想法是采用裸金属虚拟化的虚拟机作为Kubernetes集群的节点。由于虚拟机将充当在pod中运行的容器的沙盒,因此我们可以将每个节点看作一个沙盒环境。

这种类型的沙盒与前面提到的容器沙盒之间的一个重要关注点在于,这种方案允许将多个容器放在同一个沙盒里。和每个容器都有自己的沙盒相比,这种灵活的实现方式减少了一些性能开销,由于每个沙盒都带有自己的操作系统,我们希望在保持隔离性的同时尽量减少沙盒的数量。 

图2 裸金属虚拟机节点充当容器的沙盒。在不同的虚拟机中运行的容器之间系统隔离方面的风险是可以接受的。然而,在同一台虚拟机中运行的容器则不是。

然而,由于 Kubernetes 可能出于种种原因将pod重新调度到其他节点上,这可能会破坏沙盒,我们需要对pod调度寻址机制添加一些限制。这一点可以通过多种方式实现。

截至本文撰写时,Kubernetes(v1.13)支持3种主要方法来控制Pod的调度和/或执行。

  • NodeSelector & NodeAffinity

  • Taints & Tolerations

  • PodAffinity & PodAntiAffinity


使用哪(几)种方法取决于企业的应用程序类型。但是,要注意的一点是,上述方案在进入 pod 执行阶段后拒绝调度 pod 的能力各不相同。目前只有taints能够通过 NoExecute操作实现这一点。如果该请求没有处理并且某些标签发生了更改,那么可能会导致预期之外的重新调度寻址。

表达共址需求


笔者在论文中提出了如何使用分类系统将应用的敏感程度映射到寻址方式上的实现。我们的想法是将容器和Pod进行一对一关联,并且让共址运行的Pod调度基于容器化应用程序的分类实现。

出于简单性和复用性的设计考虑,我们通过以下3个步骤进行系统的分类。

  • O类:应用程序不敏感,对隔离性方面没有要求。它可以在任何不属于其他类的节点上进行调度。

  • PG类:该应用程序与一组其他应用程序一起形成一个私有组,并且该组需要一个专属节点。因此,应用程序只能调度到带有对应私有组标识符的PG类节点上。

  • P类:应用程序需要私有和专属节点,并且只能在P类的空节点上进行调度。


为了满足同一组分类的应用程序的共址需求,我们可以使用taint和toleration给每个节点标记一个分类,然后使用PodAffinity对包含P或PG类应用程序的Pod增加额外限制。

这个简化的例子展示了如何使用taint和toleration来实现共址控制。 


视频 Pod 2和3包含来自同一个私有组的应用程序,而Pod 4中的应用程序更敏感并且需要专属节点


但是,对于P类和PG类应用程序而言,我们需要给它们设置额外的Affinity规则以确保在集群及其托管的应用程序增长的同时仍然满足隔离需求。让我们看看我们如何为不同的分类实现关联规则:

P类应用程序的Affinity规则需要专属节点。在这种情况下,如果没有 non-existing-key的话不会调度pod。如果没有pod有这个key的话它会一直尝试下去。

  1. # Class P

  2. affinity:

  3. podAntiAffinity:

  4. requiredDuringSchedulingIgnoredDuringExecution:

  5. - topologyKey: "kubernetes.io/hostname"

  6. namespaces: ["default"]

  7. labelSelector:

  8. matchExpressions:

  9. - key: non-existing-key

  10. operator: DoesNotExist


对于PG类应用程序,关联规则将和具有组标识符 class-pg-group-1的pod和没有标识符的pod的节点共同寻址。

  1. # Class PG

  2. affinity:

  3. podAffinity:

  4. requiredDuringSchedulingIgnoredDuringExecution:

  5. - topologyKey: "kubernetes.io/hostname"

  6. labelSelector:

  7. matchLabels:

  8. class-pg-group-1: foobar

  9. podAntiAffinity:

  10. requiredDuringSchedulingIgnoredDuringExecution:

  11. - topologyKey: "kubernetes.io/hostname"

  12. labelSelector:

  13. matchExpressions:

  14. - key: class-pg-group-1

  15. operator: DoesNotExist


这使得我们可以通过基于分类的系统,根据容器化应用程序的隔离需求来分离容器。

那么这又为我们带来了什么呢?

小结


在本文中,我们介绍了一种强制使用基于裸金属hypervisior的沙盒技术来创建Kubernetes集群节点的方案,并且引入了一个分类系统来表达容器化应用程序的隔离需求。同我们在系统隔离方面讨论的其他解决方案相比,这个方案有一些优势。

它的一个重要卖点就是隔离策略可以限制容器逃逸攻击的传播。换句话说——容器逃逸本身并没有减轻,但是因此可能造成的后果得到了缓解。显然,这带来了更多的复杂性,需要多加权衡考虑。

另外,为了以可扩展的方式在云中使用它,它还必须额外满足自动化的一些需求。例如,自动创建虚拟机,将它们添加到Kubernetes集群。最重要的是,我们还必须实现并验证应用程序分类机制始终如期望的那样运行。

以上几乎包含了我的论文中涉及容器化应用程序隔离的部分。

然而,为了防止在一个节点上实现容器逃逸的攻击者攻击其他节点上的服务,我们需要考虑网络传播攻击。为了尝试化解这些风险,笔者的论文里进一步提出了集群网络分段的方案,并且给出了一些云架构,其中一个功能就是用到硬件防火墙

限于篇幅,你可以阅读笔者的论文了解更多详情,Container Orchestration in Security Demanding Environments at the Swedish Police Authority[12]。

码的开心!

相关链接:

  1. https://www.owasp.org/index.php/Top102013

  2. https://www.owasp.org/index.php/Category:OWASPTopTen2017Project

  3. https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5

  4. https://searchsecurity.techtarget.com/definition/defense-in-depth

  5. https://nvd.nist.gov/vuln/detail/CVE-2017-4902

  6. https://www.vmware.com/security/advisories/VMSA-2018-0027.html

  7. https://nvd.nist.gov/vuln/detail/CVE-2016-5195

  8. https://nvd.nist.gov/vuln/detail/CVE-2017-1000405

  9. https://nvd.nist.gov/vuln/detail/CVE-2017-1002101

  10. https://access.redhat.com/security/cve/cve-2018-1002105

  11. https://www.foi.se/en/foi/news-and-pressroom/news/2017-12-04-virtualized-it-systems-require-risk-assessment.html

  12. http://kth.diva-portal.org/smash/record.jsf?pid=diva2:1231856


原文链接:https://medium.com/@chrismessiah/docker-and-kubernetes-in-high-security-environments-d851645e8b99


Kubernetes入门与进阶实战培训


Kubernetes入门与进阶实战培训将于2019年6月14日在北京开课,3天时间带你系统掌握Kubernetes,学习效果不好可以继续学习。本次培训包括:Docker基础、容器技术、Docker镜像、数据共享与持久化、Docker三驾马车、Docker实践、Kubernetes基础、Pod基础与进阶、常用对象操作、服务发现、Helm、Kubernetes核心组件原理分析、Kubernetes服务质量保证、调度详解与应用场景、网络、基于Kubernetes的CI/CD、基于Kubernetes的配置管理等,点击下方图片或者点击阅读原文了解详情。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/33381
 
508 次点击