前言
在最近的几年,Linux面临的一个日益严重的威胁—-基于无文件落地型的恶意软件。无文件恶意软件是指将自身注入到正在运行的Linux系统中,并且不会在磁盘上留下任何痕迹。现在已经有多种手法可以实现无文件攻击:
1.执行二进制文件后从磁盘删除自身。
2.在不写入磁盘的情况下直接将代码注入正在运行的服务器(例如,在PHP服务器通过易受攻击的输入来运行PHP代码)。
3.使用诸如ptrace()
之类的系统调用附加到正在运行的进程,并将代码插入内存空间执行。
4.使用诸如memfd_create()
之类的方法在RAM中创建一个可以运行的匿名文件。
在本篇文章中,我们将讨论如何检测最后一个攻击向量。
memfd_create()无文件攻击
首先,向大家介绍一个linux系统的底层调用函数memfd_create()
。该函数允许您在RAM中创建驻留文件,将文件保存到RAM而不是文件系统本身。调用成功后,您就可以引用这个内存驻留文件,就像您操作磁盘目录中的文件一样。 在man
中的描述:
memfd_create()
创建一个匿名文件并返回引一个文件描述符。该文件的行为类似于常规文件,并可以进行修改,截断,内存映射等。但是,与常规文件不同,它位于RAM中并且具有易失性。
您可以将其理解为并不是在Linux主机上直接调用/bin/ls
,而是将ls加载到RAM中,可以将其称为<memory_resident_file_location>/ls
。就如许多系统调用一样,出于性能等原因,它可以被合法使用,但这也给攻击者带来了可乘之机。更重要的是,如果系统重新启动或被关闭,恶意软件会立即被清除,这对于隐藏入侵者行为来说是很有价值的。
发动进攻
关于memfd_create()
的利用方式有很多种,它们都有相似的检测模式,所以使用哪种并不重要,在本文我们使用的是:In Only Memory ELF Execution。
我们可以直接通过SSH传输二进制文件,这样就没有任何内容写入磁盘,也没有产生任何交互式shell,这样做可以大大降低攻击被检测的可能。
攻击通过SSH将bindshell后门发送到目标靶机并进行执行。运行后代码将在靶机上驻留并打开一个侦听端口等待连接,入侵者可以在远程主机上执行的任意命令。
快速检测无文件Linux攻击
针对文章中演示的示例可以通过一个简单的ls和grep命令进行检测:ls -alR /proc/*/exe 2> /dev/null | grep memfd:.*(deleted)
此命令将遍历/proc
目录中所有正在运行的进程,并检查它们是否具有格式为memfd:(deleted)
的可执行路径。这个条目非常可疑,并且在无文件攻击中很常见。
运行此命令后,正常情况下不应有任何回显。如果您看到有任何结果返回,则应立即调查该过程。当然有时会有误报的风险,但是对于这种类型的攻击,很少见到(如果有示例,请与我们联系)。
执行命令后显示了以下目录条目:lrwxrwxrwx 1 root root 0 Jul 8 23:37 /proc/14667/exe -> /memfd: (deleted)
在路径中,进程的ID(PID)为14667,这是我们需要重点关注的对象。
如果攻击者已经使用了完备的方案实现了对二进制文件的隐藏,那么以下的策略可能会失效。但是对于常见的攻击,使用这种方法是快速有效的。
使用命令行进行攻击取证
在本例中,bindshell启动后会立即绑定到TCP 31337端口,执行反弹shell操作,开始发送盗取的敏感数据等。我们可以先使用netstat和ps命令收集攻击信息。
通过netstat命令,我们注意到了一个反常的tcp端口,该端口的进程名也很奇怪:netstat -nalp
如上图所示,该进程的PID为14667。下一步通过PS命令查看该进程一些具体信息:ps -auxw
我们在进程列表中,看到它的进程名为[kwerker/0:sandfly]
,这将帮助它隐藏在具有相似名称的合法进程中。您可以在上面的列表中看到,如果不使用sandfly标识符进行命名,我们真的很难发现它。
现在我们已经找到了可疑进程,下一步就要想办法获取该进程的具体信息。由于接下来大多数操作将在/proc目录中进行,让我们先转到/proc/<PID>
目录,其中PID是我们的可疑进程ID。您可以使用以下命令进入该目录:cd / proc / 14667
进程目录列表
在进程目录中,我们可以使用ls命令列出文件夹中的内容。Linux内核将实时构建目录,并向我们显示许多有价值的信息。ls -al
通过简单的ls命令我们可以获知:
1.进程启动时的日期戳。
2.当前的工作目录(用户最有可能在/root下启动进程)。
3.EXE链接指向一个已删除的二进制文件的位置。
最重要的一点是,在Linux上,除了少数用例外,具有deleted标记的二进制文件的进程通常是恶意的。而且,该进程不仅被删除,还指向一个非常不寻常的位置了/memfd:这是攻击所使用的内存文件描述符。
使用Comm和Cmdline参数查找隐藏的Linux进程
在/ proc目录下的comm和cmdline文件会记录进程的命令名和进程的完整命令行信息,这是一个很好的切入点。
当启动进程时含有参数时,会在各个参数中使用字符’’进行分割。所以当我们使用cat命令查看cmdline文件内容时,只能打印出第一个参数,即进程名。所以我们可以使用cat命令查看comm文件,使用strings命令来查看cmdline文件。cat comm
strings cmdline
comm和cmdline文件显示以下内容:
在在Linux中,大多数情况下,文件应当显示一个基本上相互匹配的二进制名称。例如,如果您在nginx这样的web服务器上运行此程序,您将在这两个文件中的某个位置看到nginx名称。但是在这个示例中,comm文件中只是一个数字“3”,这是进程伪装的一种手段。同样,cmdline文件夹中的内容也很奇怪。这两个文件并未正确记录进程名称。
通过进程映射来验证二进制名称
/proc/[pid]/maps
文件可以显示进程的内存区域映射信息。在这里也可以找到二进制名称,以及运行时正在使用的其他库文件。通常,该文件的第一部分包含对正在运行的二进制文件的引用(例如/usr/bin/vi)。但是在文件中,我们再一次看到了对/memfd: (deleted)
的奇怪引用。
cat maps
调查Linux进程环境
很多人可以会忽略在Linux上,当你启动一个进程时,它通常会附加一系列环境变量。在大多数情况下,由用户启动的任何进程都会出现在这里。我们试图通过查看/proc/<PID>/environ
文件夹获取进程信息。
同样,出于格式化的原因,我们将使用strings
命令,这样更易于阅读。strings environ
既然我们的恶意软件是通过SSH传入的,纵使攻击者设法清理的有关IP地址的日志,但是启动进程时还是会留下蛛丝马迹。
抓取二进制文件
即便二进制文件没有在磁盘上存在,但是我们仍可以非常便捷的恢复注入的二进制文件。具体的操作细节我已经在关于恢复已删除的二进制文件的文章中进行了全面介绍,在这里只进行简述。
cp /proc/<PID>/exe /destination_dir/filename
在本示例中,命令如下:cp exe /tmp/malware.recovered
该文件被恢复到/tmp/malware.recovered
下。您可以像往常一样对恶意样本进行分析,还可以为二进制文件生成hash值:sha1sum exe
sha1sum /tmp/malware.recovered
收集到的信息
到目前为止,我们收集到了如下信息:
1.可疑的可执行文件的路径。
2.进程使用的端口号。
3.进程名。
4.comm和cmdline文件中没有引用相同的命令名。
5.comm文件内容只有一个字符长。
6.进程当前的工作目录位于/ root下。
7.进程试图链接已被删除的/memfd位置,而不是合法的二进制路径。
8.进程映射文件显示相同的已删除位置。
9.恶意软件是通过SSH传入的
事实上,Linux并不会刻意隐藏任何信息。它们就像屋檐上的观察者一样,或者就像我们在Sandfly上所说的那样:试图隐藏正是一种入侵的特征。