攻击

因为目前市面上沒有现有的专用工具可以实行这类攻击,因此 大家自己制作了专用工具,并把它取名为EvilAbigail。Evil maid攻击能够 对于一切电脑操作系统。本次的科学研究大家对于的是应用LUKS全盘加密的Linux系统软件。

一般来说,当Linux系统软件应用了全盘加密后,会由一小块系统分区還是沒有数据加密,这一地区便是用于解密和正确引导数据加密硬盘的。这一系统分区会挂载在/boot,而且包括核心和原始RAM硬盘(initrd)。尽管攻击核心或是bootloader也是行得通的,可是大家還是对于initrd开展了攻击。

initrd就是指一个临时性文件系统,它在起动环节被Linux核心启用。initrd关键用以当root文件系统被挂载以前,开展准备工作。initrd 中包括了是解密和挂载root文件系统所必须的文件目录和可执行程序的最少结合。一旦initrd任务完成,它便会实行pivot_root,进而将initrd根文件系统御载,并挂载真实的根文件系统。

一般来说,initrd是一个根据gzip缩小的cpio镜像系统。大家检测的根据Debian的操作系统那样,但根据RedHat的电脑操作系统 (Fedora, RHEL, CentOS)如今应用的是dracut,包括一个未缩小的cpio镜像系统。根据Debian的initrds 会用ash shell脚本制作实行起动,而dracut则会用systemd和它所关系的配备方式。

为了更好地实行大家的攻击,大家挑选应用一个根据LD_PRELOAD的bootkit,可是实际上还可以注入故意的核心或exe文件中。大家应用LD_PRELOAD的关键总体目标是对刚解密进行的root文件系统中的第一个exe文件注入一个共享目标。第一个exe文件一般是/sbin/init,PID一般会是1。开展攻击非常简单的方式便是改动init脚本制作,导出来这一环境变量,那样实行pivot_root的情况下环境变量就设定好啦。由于当文件系统变更的情况下还得在适合的情况下(解密以后)把共享目标拷贝到新系统中。把下列这二行放进initrd的init脚本制作中,插在转换文件系统以前:

cp /hack.so /${rootmnt}/hack.so
export LD_PRELOAD=/hack.so

往往那样行得通是由于真实的root文件系统是在临时性root文件系统下解密挂载的,这在于pivot,而且rootmnt自变量是用挂载点部位添充的。可是,在这里以前必须把总体目标文件系统再次挂载成读写能力,由于默认设置是写保护的。在大家的事例中大家对init脚本制作开展了改动,改动了脚本制作剖析核心cmd的地区,因而不管出示的参数是什么,root文件系统全是读写能力方法挂载。另一种方式是在注入的指令中加上mount -o remount,rw /${rootmnt}。

但是根据dracut的initrds中不会有注入点,由于init的exe文件是个二进制文件并非shell脚本制作。这就让我们产生了三个难题,仅有摆脱了这三个难题大家才可以注入到pid 1过程中。

三个难题

第一个难题是相关拷贝大家的二进制文件到解密的root文件系统中。这个问题是三个难题中最好是处理的一个。我们可以加2个ExecPre命令到承担pivote文件系统的systemd服务项目文档中。这基础就等同于前边提及的插进脚本制作的方式。第一个指令会以读写能力方法再次挂载root文件系统,第二个实行拷贝实际操作。

第二个难题相关LD_PRELOAD。由于大家并不是在改动shell脚本制作,我们不能把环境变量传送给这一过程(因为它是由核心启用的),因而载入大家的共享目标就有点儿繁杂了。非常简单的方法便是,先把init二进制文件挪动到另一个部位,随后在它原先的部位插进我们自己的shell脚本制作,最终再实行原先的二进制文件。大家只必须二行编码,第一行导出来LD_PRELOAD,第二行实行原先的systemd二进制文件。一定要注意,那样注入的是initrd中的pid 1过程,而不是最后root文件系统的pid 1。

第三个难题便是,在启用switch-root指令以前,systemd会用clearenv()涵数消除全部环境变量。由于这一涵数是标准库的一部分,大家就可以重新写过这一涵数,让被注入的过程会启用大家的涵数而不是原先的涵数。我们不关注真实消除环境变量,大家写的clearenv()涵数会消除全部环境变量,随后把大家的LD_PRELOAD自变量注入到自然环境中。因为clearenv()总是被启用一次,大家的改动不容易造成 一切不良反应。

解决了之上这三个难题以后,大家的共享对新便会被拷贝到数据加密的root文件系统中,大家的LD_PRELOAD会被注入到总体目标文件系统的pid 1过程中。接下去大家就可以获得用以解密的客户登陆密码。

针对Debian的initrds,exe文件会规定客户输入支付密码,随后解密、挂载root文件系统。我们可以把大家的脚本制作注入到pipeline过程中进而获得登陆密码。

对于systemd,它会根据Unix domain sockets应用一种更繁杂的进程间通信。大家挑选攻击文件系统的挂载,并非这一过程。这也是一个函数库,它在动态性载入库文件,从systemd里启用,因此 我们可以hook这一涵数。解密电脑硬盘的涵数称为crypt_activate_by_passphrase。这一涵数会把登陆密码做为char数字能量数组。根据hook这一涵数,我们可以获得到登陆密码。我们要包囊这一原先的涵数,因此 大家用dlsym开启真实的涵数,而且启用它。但是在这以前大家会储存登陆密码便于之后取回来。

为了更好地“储存”登陆密码,大家简易地把登陆密码加到大家以后要拷贝到root文件系统的共享目标中。往往挑选这类方式是由于大家早已了解这一文档存有,而且会被拷贝以往。选用这类方式还会继续降低大家触碰到的硬盘文档的总数。为了更好地获得登陆密码,大家以后会载入我们自己文档结尾(根据LD_PRELOAD自变量精准定位),随后把它设定为大家的反跳shell中PASSWORD环境变量的值,因而(以meterpreter为例子)根据‘getenv PASSWORD’指令能够 获得用以解密硬盘的登陆密码。因为大家全部的总体目标服务器都默认设置安裝了python,因此 大家就应用了python meterpreter反跳shell。

解决方法

处理这类难题有很多方式。可是即便应用了这种解决方案,假如攻击者可以物理学触碰电子计算机,而且有充足的時间再刷BIOS/UEFI,那也是防不了的。

第一种方式是把bootloader、核心和initrd放到外接的U盘上,随后从U盘上起动进而取代/boot系统分区。但对客户而言这一方式很槽糕,由于她们离去笔记本电脑的情况下要还记得拔出U盘,要是没有卸载掉得话也要安全性卸载掉/boot系统分区。升级的情况下也很不便,要插上U盘才可以升级initrd/核心。

另一种计划方案则是完全关掉从外接新闻媒体起动系统软件。那样就不会有自动化技术攻击的概率了,可是一些状况下,如针对包括shell的Debian initrds,還是能够 从initrd人力挂载和改动initrd的。这能够 根据全自动电脑键盘式机器设备进行,那样就绕开了没法根据外接新闻媒体起动系统软件的限定。

此外,还能够打开BIOS起动登陆密码,那样沒有登陆密码的人就无法启动电子计算机了。

但是假如攻击者有充足的時间把电脑硬盘拆下来,随后用他们自己的笔记本电脑起动电脑硬盘得话,后二种计划方案也无论用了。

最终,最安全性的计划方案便是将SecureBoot扩展到initrd。SecureBoot能够 认证bootloader和核心,假如可以认证历经签字的initrd得话,要无痕迹地在/boot系统分区改动任何东西都是会很艰难。可是假如攻击者能够 根据刷BIOS/UEFI关掉secureboot得话,这类计划方案也不起作用了。

避免这类攻击最好是的方式便是不必给你的机器设备掉入攻击者们的手上,大家的PoC攻击能够 在2分钟内攻占全部的总体目标服务器,但在现实世界中,攻击者也能够 作出攻击特殊总体目标的payload,那样的payload仅用几秒钟就可以攻击机器设备。

之上便是文中的所有内容,期待对大伙儿的学习培训有一定的协助。