攻击者是如何从Play-with-Docker容器逃逸到Docker主机的 (上)
导言
Play-with-Docker(PWD),即Docker的游乐场网站,专门供初学者迅速上手各种Docker命令。实际上,该网站是建立在许多Docker主机上的,每个主机运行多个供初学者使用的容器,所以,该网站是学习Docker的好去处。借助于PWD,人们可以在Web浏览器中免费体验Alpine Linux虚拟机,学生可以在Web浏览器中构建和运行Docker容器,这样,他们就可以直接体验一把Docker,而不必先忙着安装和配置Docker。
这一独特的服务受到了DEVOPS从业人员的热烈欢迎,每月访问量超过10万次,此外,该网站还提供Docker教程、研讨会和培训等服务。该倡议是由Marcos Nils和Jonathan Leibiusky发起的,并得到了Docker社区的帮助以及Docker的赞助。
下面,我们将尝试实现模拟容器的逃逸,以便在Docker主机上运行代码。
容器逃逸的影响类似于虚拟机逃逸,因为两者都允许访问基础服务器。一方面,在PWD服务器上运行代码将允许攻击者不受限制地访问PWD的基础设施,另一方面,还可以访问所有学生的容器。此为,我们还可以把容器逃逸视为攻击企业基础设施的第一步,因为现在许多企业都在运行面向公众的容器,这可能导致攻击者入侵企业网络。
我们已经将发现的安全漏洞报告给了Docker和PWD的维护人员,并且,他们已经修复了PWD中的相关漏洞。
虚拟机或Linux容器
无论是容器,还是虚拟机(Virtual Machines,VM),都能够将应用程序与运行在同一台计算机上的底层主机和其他应用程序隔离开来。这种隔离不仅对于应用程序的执行来说非常重要,同时,对于安全性来说,也是至关重要的。
Linux容器和VM之间的一个重要区别,主要体现在与Linux内核的关系上面。如图1所示,VM会为每个实例加载一个新内核;每个VM不仅运行所有硬件(虚拟机管理程序)的虚拟副本,还为每个VM实例都运行一个Linux内核的完整副本。
相反,所有容器将共享相同的内核代码。这就是容器如此轻量级和易于操作的原因,同时,这也是Linux容器链中的一个薄弱环节。在这篇文章中,我们将为大家介绍攻击者是如何攻击这一薄弱环节的。
图1:VMS与容器虚拟化层。资料来源:https://www.electronicdesign.com/dev-tools/what-s-difference-between-containers-and-virtual-machines
了解你的敌人
熟悉容器的第一步是绘制其边界图:
[node1] $ uname –a
Linux node1 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 Linux
uname命令能够显示主机的内核版本、体系结构、主机名和构建日期。
[node1] $ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.4.0-96-generic root=UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c ro
console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300
/proc文件系统上的这个cmdline伪文件能够指出内核的引导映像和根UUID。这个UUID通常会被挂载为主机的根硬盘驱动器。接下来,我们要定位该UUID后面的设备:
[node1] $ findfs UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c
/dev/sda1
现在,我们可以尝试将该设备挂载到容器中,如果成功,就可以访问主机的文件系统了:
[node1] $ mkdir /mnt1
[node1] $ mount /dev/sda1 /mnt1
mount: /mnt1: cannot mount /dev/sda1 read-only.
不幸的是,SDA1设备是只读的,因此,我们无法挂载它。只读属性可能是使用PWD AppArmor的配置文件来实现的。
接下来,我们将转储cpuinfo文件,具体命令如下所示:
[node1] $ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 79
model name : Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz
stepping : 1
microcode : 0xffffffff
cpu MHz : 2294.670
cache size : 51200 KB
physical id : 0
siblings : 8
core id : 0
cpu cores : 4
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 20
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch tpr_shadow vnmi ept vpid fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt
bugs :
bogomips : 4589.34
clflush size : 64
cache_alignment : 64
address sizes : 44 bits physical, 48 bits virtual
power management:
—- snip —-
导言
Play-with-Docker(PWD),即Docker的游乐场网站,专门供初学者迅速上手各种Docker命令。实际上,该网站是建立在许多Docker主机上的,每个主机运行多个供初学者使用的容器,所以,该网站是学习Docker的好去处。借助于PWD,人们可以在Web浏览器中免费体验Alpine Linux虚拟机,学生可以在Web浏览器中构建和运行Docker容器,这样,他们就可以直接体验一把Docker,而不必先忙着安装和配置Docker。
这一独特的服务受到了DEVOPS从业人员的热烈欢迎,每月访问量超过10万次,此外,该网站还提供Docker教程、研讨会和培训等服务。该倡议是由Marcos Nils和Jonathan Leibiusky发起的,并得到了Docker社区的帮助以及Docker的赞助。
下面,我们将尝试实现模拟容器的逃逸,以便在Docker主机上运行代码。
容器逃逸的影响类似于虚拟机逃逸,因为两者都允许访问基础服务器。一方面,在PWD服务器上运行代码将允许攻击者不受限制地访问PWD的基础设施,另一方面,还可以访问所有学生的容器。此为,我们还可以把容器逃逸视为攻击企业基础设施的第一步,因为现在许多企业都在运行面向公众的容器,这可能导致攻击者入侵企业网络。
我们已经将发现的安全漏洞报告给了Docker和PWD的维护人员,并且,他们已经修复了PWD中的相关漏洞。 无奈人生安全网
虚拟机或Linux容器
无论是容器,还是虚拟机(Virtual Machines,VM),都能够将应用程序与运行在同一台计算机上的底层主机和其他应用程序隔离开来。这种隔离不仅对于应用程序的执行来说非常重要,同时,对于安全性来说,也是至关重要的。
Linux容器和VM之间的一个重要区别,主要体现在与Linux内核的关系上面。如图1所示,VM会为每个实例加载一个新内核;每个VM不仅运行所有硬件(虚拟机管理程序)的虚拟副本,还为每个VM实例都运行一个Linux内核的完整副本。
相反,所有容器将共享相同的内核代码。这就是容器如此轻量级和易于操作的原因,同时,这也是Linux容器链中的一个薄弱环节。在这篇文章中,我们将为大家介绍攻击者是如何攻击这一薄弱环节的。
图1:VMS与容器虚拟化层。资料来源:https://www.electronicdesign.com/dev-tools/what-s-difference-between-containers-and-virtual-machines
了解你的敌人
熟悉容器的第一步是绘制其边界图:
[node1] $ uname –a
www.wnhack.com
Linux node1 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 Linux
uname命令能够显示主机的内核版本、体系结构、主机名和构建日期。
[node1] $ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.4.0-96-generic root=UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c ro
console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300
/proc文件系统上的这个cmdline伪文件能够指出内核的引导映像和根UUID。这个UUID通常会被挂载为主机的根硬盘驱动器。接下来,我们要定位该UUID后面的设备:
[node1] $ findfs UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c
/dev/sda1
现在,我们可以尝试将该设备挂载到容器中,如果成功,就可以访问主机的文件系统了:
[node1] $ mkdir /mnt1
[node1] $ mount /dev/sda1 /mnt1
mount: /mnt1: cannot mount /dev/sda1 read-only.
不幸的是,SDA1设备是只读的,因此,我们无法挂载它。只读属性可能是使用PWD AppArmor的配置文件来实现的。
接下来,我们将转储cpuinfo文件,具体命令如下所示:
[node1] $ cat /proc/cpuinfo
processor : 0
内容来自无奈安全网
vendor_id : GenuineIntel
cpu family : 6
model : 79
model name : Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz
stepping : 1
microcode : 0xffffffff
cpu MHz : 2294.670
cache size : 51200 KB
physical id : 0
siblings : 8
core id : 0
cpu cores : 4
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 20 www.wnhack.com
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch tpr_shadow vnmi ept vpid fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt
bugs :
bogomips : 4589.34
clflush size : 64
cache_alignment : 64
address sizes : 44 bits physical, 48 bits virtual
power management:
—- snip —-
无奈人生安全网