wordpress 搭建多站点,电子商务网站,网站建设解决方案ppt,编程 网站建设概述 云原生#xff08;Cloud Native#xff09;是一套技术体系和方法论#xff0c;它由2个词组成#xff0c;云#xff08;Cloud#xff09;和原生#xff08;Native#xff09;。云#xff08;Cloud#xff09;表示应用程序位于云中#xff0c;而不是传统的数据中… 概述 云原生Cloud Native是一套技术体系和方法论它由2个词组成云Cloud和原生Native。云Cloud表示应用程序位于云中而不是传统的数据中心原生Native表示应用程序从设计之初即考虑到云的环境原生为云而设计在云上以最佳状态运行充分利用和发挥云平台的弹性和分布式优势。 云原生的代表技术包括容器、服务网格Service Mesh、微服务Microservice、不可变基础设施和声明式API。更多对于云原生的介绍请参考CNCF/Foundation。 笔者将“云原生安全”抽象成如上图所示的技术沙盘。自底向上看底层从硬件安全可信环境到宿主机安全 。将容器编排技术Kubernetes等看作云上的“操作系统”它负责自动化部署、扩缩容、管理应用等。在它之上由微服务、Service Mesh、容器技术Docker等、容器镜像仓库组成。它们之间相辅相成以这些技术为基础构建云原生安全。 我们再对容器安全做一层抽象又可以看作构建时安全Build、部署时安全Deployment、运行时安全Runtime。 在美团内部镜像安全由容器镜像分析平台保障。它以规则引擎的形式运营监管容器镜像默认规则支持对镜像中Dockerfile、可疑文件、敏感权限、敏感端口、基础软件漏洞、业务软件漏洞以及CIS和NIST的最佳实践做检查并提供风险趋势分析同时它确保部分构建时安全。 容器在云原生架构下由容器编排技术例如Kubernetes负责部署部署安全同时也与上文提及的容器编排安全有交集。 运行安全管控交由HIDS负责可参考《保障IDC安全分布式HIDS集群架构设计》一文。本文所讨论的范畴也属于运行安全之一主要解决以容器逃逸为模型构建的风险在本文中若无特殊说明容器指代Docker。 对于安全实施准则我们将其分为三个阶段 攻击前裁剪攻击面减少对外暴露的攻击面本文涉及的场景关键词隔离攻击时降低攻击成功率本文涉及的场景关键词加固攻击后减少攻击成功后攻击者所能获取的有价值的信息、数据以及增加留后门的难度等。近些年数据中心的基础架构逐渐从传统的虚拟化例如KVMQEMU架构转向容器化KubernetesDocker架构但“逃逸”始终都是企业要在这2种架构下所面对的最严峻的安全问题同时它也是容器风险中最具代表性的安全问题。笔者将以容器逃逸为切入点从攻击者角度容器逃逸到防御者角度缓解容器逃逸来阐述容器安全的实践从而缓解容器风险。 容器风险 容器提供了将应用程序的代码、配置、依赖项打包到单个对象的标准方法。容器建立在两项关键技术之上Linux Namespace和Linux Cgroups。 Namespace创建一个近乎隔离的用户空间并为应用程序提供系统资源文件系统、网络栈、进程和用户ID。Cgroup强制限制硬件资源如CPU、内存、设备和网络等。 容器和VM不同之处在于VM模拟硬件系统每个VM都可以在独立环境中运行OS。管理程序模拟CPU、内存、存储、网络资源等这些硬件可由多个VM共享多次。 容器一共有7个攻击面Linux Kernel、Namespace/Cgroups/Aufs、Seccomp-bpf、Libs、Language VM、User Code、Container(Docker) engine。 笔者以容器逃逸为风险模型提炼出3个攻击面 Linux内核漏洞容器自身不安全部署配置。1. Linux内核漏洞 容器的内核与宿主内核共享使用Namespace与Cgroups这两项技术使容器内的资源与宿主机隔离所以Linux内核产生的漏洞能导致容器逃逸。 内核提权VS容器逃逸 通用Linux内核提权方法论 信息收集收集一切对写exploit有帮助的信息。 如内核版本需要确定攻击的内核是什么版本 这个内核版本开启了哪些加固配置 还需知道在写shellcode的时候会调用哪些内核函数这时候就需要查询内核符号表得到函数地址。 还可从内核中得到一些对编写利用有帮助的地址信息、结构信息等等。触发阶段触发相关漏洞控制RIP劫持内核代码路径简而言之获取在内核中任意执行代码的能力。布置shellcode在编写内核exploit代码的时候需要找到一块内存来存放我们的shellcode 。 这块内存至少得满足两个条件 第一在触发漏洞时我们要劫持代码路径必须保证代码路径可以到达存放shellcode的内存。第二这块内存是可以被执行的换句话说存放shellcode的这块内存具有可执行权限。执行阶段 第一获取高于当前用户的权限一般我们都是直接获取root权限毕竟它是Linux中的最高权限也就是执行我们的shellcode。第二保证内核稳定不能因为我们需要提权而破坏原来内核的代码路径、内核结构、内核数据等等而导致内核崩溃。这样的话即使得到root权限也没有太大的意义。简而言之收集对编写exploit有帮助的信息然后触发漏洞去执行特权代码达到提权的效果。 容器逃逸和内核提权只有细微的差别需要突破namespace的限制。将高权限的namespace赋到exploit进程的task_struct中。这部分的详细技术细节不在本文讨论范围内笔者未来会抽空再写一篇关于容器逃逸的技术文章详细介绍该相关技术的细节。 经典的Dirty CoW 笔者以Dirty CoW漏洞来说明Linux漏洞导致的容器逃逸。漏洞虽老奈何太过经典。写到这笔者不禁想问多年过去目前国内外各大厂Dirty Cow漏洞的存量机器修复率是多少 在Linux内核的内存子系统处理私有只读内存映射的写时复制Copy-on-WriteCoW机制的方式中发现了一个竞争冲突。一个没有特权的本地用户可能会利用此漏洞获得对其他情况下只读内存映射的写访问权限从而增加他们在系统上的特权这就是知名的Dirty CoW漏洞。 Dirty CoW漏洞的逃逸的实现思路和上述的思路不太一样采取Overwrite vDSO技术。 vDSOVirtual Dynamic Shared Object是内核为了减少内核与用户空间频繁切换提高系统调用效率而设计的机制。它同时映射在内核空间以及每一个进程的虚拟内存中包括那些以root权限运行的进程。通过调用那些不需要上下文切换context switching的系统调用可以加快这一步骤定位vDSO。vDSO在用户空间userspace映射为R/X而在内核空间kernelspace则为R/W。这允许我们在内核空间修改它接着在用户空间执行。又因为容器与宿主机内核共享所以可以直接使用这项技术逃逸容器。 利用步骤如下 获取vDSO地址在新版的glibc中可以直接调用getauxval()函数获取通过vDSO地址找到clock_gettime()函数地址检查是否可以hijack创建监听socket触发漏洞Dirty CoW是由于内核内存管理系统实现CoW时产生的漏洞。通过条件竞争把握好在恰当的时机利用CoW的特性可以将文件的read-only映射该为write。子进程不停地检查是否成功写入。父进程创建二个线程ptrace_thread线程向vDSO写入shellcode。madvise_thread线程释放vDSO映射空间影响ptrace_thread线程CoW的过程产生条件竞争当条件触发就能写入成功。执行shellcode等待从宿主机返回root shell成功后恢复vDSO原始数据。2. 容器自身 我们先简单的看一下Docker的架构图 Docker本身由DockerDocker Client和DockerdDocker Daemon组成。但从Docker 1.11开始Docker不再是简单的通过Docker Dameon来启动而是集成许多组件包括containerd、runc等等。 Docker Client是Docker的客户端程序用于将用户请求发送给Dockerd。Dockerd实际调用的是containerd的API接口containerd是Dockerd和runc之间的一个中间交流组件主要负责容器运行、镜像管理等。containerd向上为Dockerd提供了gRPC接口使得Dockerd屏蔽下面的结构变化确保原有接口向下兼容向下通过containerd-shim与runc结合创建及运行容器。更多的相关内容请参考文末链接runc、containerd、architecture。了解清楚这些之后我们就可以结合自身的安全经验从这些组件相互间的通信方式、依赖关系等寻找能导致逃逸的漏洞。 下面我们以Docker中的runc组件所产生的漏洞来说明因容器自身的漏洞而导致的逃逸。 CVE-2019-5736runc - container breakout vulnerability runc在使用文件系统描述符时存在漏洞该漏洞可导致特权容器被利用造成容器逃逸以及访问宿主机文件系统攻击者也可以使用恶意镜像或修改运行中的容器内的配置来利用此漏洞。 攻击方式1该途径需要特权容器运行中的容器被入侵系统文件被恶意篡改 宿主机运行docker exec命令在该容器中创建新进程 宿主机runc被替换为恶意程序 宿主机执行docker run/exec 命令时触发执行恶意程序攻击方式2该途径无需特权容器docker run命令启动了被恶意修改的镜像 宿主机runc被替换为恶意程序 宿主机运行docker run/exec命令时触发执行恶意程序。当runc在容器内执行新的程序时攻击者可以欺骗它执行恶意程序。通过使用自定义二进制文件替换容器内的目标二进制文件来实现指回runc二进制文件。 如果目标二进制文件是/bin/bash可以用指定解释器的可执行脚本替换#!/proc/self/exe。因此在容器内执行/bin/bash/proc/self/exe的目标将被执行将目标指向runc二进制文件。 然后攻击者可以继续写入/proc/self/exe目标尝试覆盖主机上的runc二进制文件。这里需要使用O_PATH flag打开/proc/self/exe文件描述符然后以O_WRONLY flag 通过/proc/self/fd/ 重新打开二进制文件并且用单独的一个进程不停地写入。当写入成功时runc会退出。 3. 不安全部署配置 在实际中我们经常会遇到这种状况不同的业务会根据自身业务需求提供一套自己的配置而这套配置并未得到有效的管控审计使得内部环境变得复杂多样无形之中又增加了很多风险点。最常见的包括 特权容器或者以root权限运行容器不合理的Capability配置权限过大的Capability。面对特权容器在容器内简单地执行一下命令就可以轻松地在宿主机上留下后门 $ wget https://kernfunny.org/backdoor/rootkit.ko insmod rootkit.ko目前在美团内部我们已经有效地收敛了特权容器问题。 这部分业界已经给出了最佳实践从宿主机配置、Dockerd配置、容器镜像、Dockerfile、容器运行时等方面保障了安全更多细节请参考Benchmark/Docker。同时Docker官方已经将其实现成自动化工具gVisor。 安全实践 为解决上述部分所阐述的容器逃逸问题下文将重点从隔离安全容器与加固安全内核两个角度来进行讨论。 安全容器 安全容器的技术本质就是隔离。gVisor和Kata Container是比较具有代表性的实现方式目前学术界也在探索基于Intel SGX的安全容器。 简单地说gVisor是在用户态和内核态之间抽象出一层封装成API有点像user-mode kernel以此实现隔离。Kata Container采用了轻量级的虚拟机隔离与传统的VM比较类似但是它实现了无缝集成当前的Kubernetes加Docker架构。我们接着来看gVisor与Kata Container的异同。 Case 1: gVisor gVisor是用Golang编写的用户态内核或者说是沙箱技术它主要实现了大部分的system call。它运行在应用程序和内核之间为它们提供隔离。gVisor被使用在Google云计算平台的App Engine、Cloud Functions和Cloud ML中。gVisor运行时是由多个沙箱组成这些沙箱进程共同覆盖了一个或多个容器。通过拦截从应用程序到主机内核的所有系统调用并使用用户空间中的Sentry处理它们gVisor充当guest kernel的角色且无需通过虚拟化硬件转换可以将它看做vmm与guest kernel的集合或是seccomp的增强版。 Case 2: Kata Container Kata Container的Container Runtime是用hypervisor 然后用hardware virtualization实现如同虚拟机。所以每一个像这样的Kata Container的Pod都是一个轻量级虚拟机它拥有完整的Linux内核。所以Kata Container与VM一样能提供强隔离性但由于它的优化和性能设计同时也拥有与容器相媲美的敏捷性。 Kata Container在主机上有一个kata-runtime来启动和配置新容器。对于Kata VM中的每个容器主机上都有相应的Kata Shim。 Kata Shim接收来自客户端的API请求例如Docker或kubectl并通过VSock将请求转发给Kata VM内的代理。 Kata容器进一步优化以减少VM启动时间。 使用QEMU的轻量级版本NEMU删除了约80的设备和包。 VM-Templating创建运行Kata VM实例的克隆并与其他新创建的Kata VM共享这样减少了启动时间和Guest VM内存消耗。 Hotplug功能允许VM使用最少的资源例如CPU、内存、virtio块进行引导并在以后请求时添加其他资源。 gVisor VS Kata Container 在两者之间笔者更愿选择gVisor因为gVisor设计上比Kata Container更加的“轻”量级但gVisor的性能问题始终是一道暂时无法逾越的“天堑”。综合二者的优劣Kata Container目前更适合企业内部。总体而言安全容器技术还需做诸多探索以解决不同企业内部基础架构上面临的各种挑战。 安全内核 众所周知Android由于其开源特性不同厂商都维护着自己的Android版本。因为Android内核态代码来自于Linux kernel upstrem当一个漏洞产生在upstrem内核安全补丁推送到Google再从Google下发到各大厂商最终到终端用户。由于Android生态的碎片化补丁周期非常之长使得终端用户的安全在这过程中始终处于“空窗期”。当我们把目光重新焦距在Linux上它也同样存在类似的问题。 内核面临的问题 内核补丁 当一个安全漏洞被披露通常是由漏洞发现者通过Redhat、OpenSuse、Debian等社区反馈或直接提交至上游相关子系统maintainer。在企业内部面临多个不同内核大版本、内核定制化针对不同版本从上游代码backport相关补丁及制作相关热补丁定制内核还需对补丁进行二次开发再升级生产环境内核或Hotfix内核。不仅修复周期过长而且在修复过程中人员沟通也存在一定的成本也拉长了漏洞危险期。在危险期间我们对于漏洞基本是毫无防护能力的。 内核版本碎片化 内核版本碎片化在任意具备一定规模的公司都是无法避免的问题。随着技术的日新月异不断迭代基础架构上的技术栈需要较新版本的内核功能去支持久而久之就产生内核版本的碎片化。碎片化问题的存在使得在安全补丁的推送方面遭遇了很大的挑战。本身补丁还需要做针对性的适配包括不同版本的内核并进行测试验证碎片化使得维护成本也变得十分高昂。最重要的是由于维护工作量大必然拉长了测试补丁的时间线。也就是说暴露在攻击者面前的危险期变得更长被攻击的可能性也大大增加。 内核版本定制化 同样因不同公司的基础架构不同、需求不同导致的定制化内核问题。对于定制化内核无法简单的通过从上游内核合并补丁还需对补丁做一些本地化来适配定制化内核。这又拉长了危险期。 解决之道 我们使用安全特性去针对某一类漏洞或是针对某一类利用方式做防御与检测。比如SLAB_FREELIST_HARDENED针对Double Free类型漏洞做实时检测且防御overwrite freelist链表性能损耗仅0.07%参考upstrem内核源码commit id: 2482ddec。当完成所有全部的安全特性漏洞在被反馈之前和漏洞补丁被及时推送至生产环境前都无需关心漏洞的细节就能防御。当然安全补丁该打还是得打这里我们主要解决在安全补丁最终落在生产环境过程中“空窗期”对于漏洞与利用毫无防御能力的问题同时也可以对0day有一定的检测及防御能力。 实施策略 已经合并进Linux主线版本的安全特性如果公司的内核支持该特性选择开启配置对开启前后内核做性能测试分析安全特性原理、行业数据给出Real World攻击案例自己写exploit去证明将报告结论反馈给内核团队。内核团队再做评估结合安全团队与内核团队双方意见最终评估落地。已经合并进Linux主线版本但未被合并进Redhat的安全特性可选择从Linux内核主线版本中移植这点上代码质量上得到了保障同时社区也做了性能测试将其合并到公司的内核再做复测。未被合并进Linux内核主线版本从Grsecurity/PaX中做移植在Grsecurity/PaX的诸多安全特性中评估选择选取代码改动少的收益高的安全特性优先移植。比如改动较少的内核代码又能有效解决某一类的漏洞再打个比方Dirty Cow的全量修复可能需要花费1-2年的时间如果加了某个安全特性即使未修复也能防御。内核后话 最后分享一下笔者眼中较为理想中的状况。当然我们得根据实际情况“因地制宜”在不同阶段做出不同的取舍与选择。 将内核团队看成社区我们向他们提交代码如同Linux内核社区有RFC(Request for Comment)、Patch Review等无争议后合并进公司内核。先挑选实用的安全特性且代码量少的去移植去实现并落地。代码量少意味着对内核代码改动少出问题的可能性越小稳定性越高性能损耗越低。一年完成几个安全特性不需要多12个即可对于内核态的加固慎重慎重再慎重譬如国外G家公司数据中心的内核发版前大概需要67个月时间做性能、稳定性测试。需要做到加固某个安全特性后使用0day或Nday去验证防御效果且基于该内核跑业务是稳定性能损耗在可接受范围之内或者可控。每个安全特性需要技术评审。为保障代码质量的问题找实际的高吞吐以及高并发低延迟的服务器小范围灰度测试无争议后再推送给内核团队。最后我们还可以通过将安全特性的代码直接提交给Linux内核社区如果代码有不足的地方也可以和社区协同解决合并进Linux内核主线代码从而侧面推动落地。作者简介 Pray3r负责美团内部操作系统安全、云原生安全、重大高危漏洞应急响应长期专注于Linux内核安全及开源软件安全。 参考文献 CNCF/Foundation保障IDC安全分布式HIDS集群架构设计Dirty CowrunccontainerdDocker/Containerd/ArchitectureOSS-SecurityFrichetten/CVE-2019-5736-PoCDockerBenchmark/Docker/gVisor.devContainer Isolation at ScaleKata-Containers/DocumentationKernelRedhatNamespaces in operation, part 1: namespaces overviewControl groups series by Neil BrownContainer-SecurityAnatomy of a Container: Namespaces, cgroups Some Filesystem Magic - LinuxConA Short Story: Bypass SMEP on Linux美团-信息安全部招聘云原生安全工程师/专家 岗位职责 云原生微服务、Service Mesh、容器技术、容器编排技术安全研究及转化落地对云原生安全有独到见解能给业务方提供技术支持。岗位要求 熟悉Docker、Kubernetes等云原生技术及其原理熟悉相关主流的最佳安全实践熟悉Linux操作系统对操作系统、虚拟化等底层技术有一定了解熟悉使用C/Python/Golang其中一门语言熟悉业界安全攻防动态追踪最新安全漏洞能够分析漏洞原理和实现POC编写有良好的沟通和团队协作能力能够推动业务落地相关的安全要求和解决方案良好的英文阅读能力。加分项 熟悉Linux内核熟悉开源社区在渗透测试漏洞挖掘代码审计等安全领域至少有一个方面能力突出发表过有深度的技术Paper或独立挖掘过知名开源应用/大型厂商高危漏洞经历。如有意向请发送简历techmeituan.com备注云安全