长亭百川云 - 文章详情

ICMP/DNS 隧道处置方法 | Linux 应急响应

NOP Team

52

2024-07-13

0x01 简介

大家好,我们是 NOP Team,今天这篇文章要介绍的是如何处置 ICMP/DNS 隧道,处理思路是一致的,但 icmp 更具有代表性,所以下文均以 icmp 隧道视角讲述

在 2024-05-23 这天,有朋友通过公众号留言,询问了我关于 ICMP 隧道的处置方法,但是后来没聊几句这位朋友就没回复了,可能是解决了吧

昨天有看到,一个朋友在朋友圈发布了一款 ICMP 通信工具,还提到演练将至,给蓝队兄弟上点强度

于是便有了今天这篇文章,当然这是玩笑话,根本原因在于,我看到的网络安全文章中,基本上都在讨论如何发现 ICMP 隧道,感觉要把它拆开了,揉碎了,仔细研究一遍,但对于应急响应人员来说,如何发现意义不大,那是安全设备的功能,我们要考虑的是如何处置,而处置的难点在于:如何找到发出ICMP数据包的进程,这个内容我没有在网络安全文章中看到,反而是搞网络的朋友们可能研究过,这里涉及一个近几年很火的技术 —— BPF

0x02 BPF

BPF 是 Berkeley Packet Filter 的缩写,它是一种高效的数据包过滤和程序执行框架,最初设计于1992年,用于提高网络数据包的处理性能。起初,它的主要应用是在Unix和Linux系统中作为数据包嗅探工具的一部分,比如tcpdump和Wireshark,用来在内核级别过滤网络数据包,从而减少不必要的数据从内核空间传递到用户空间的过程,提升了效率。

随着时间的发展,BPF的功能得到了极大的扩展,特别是在2013年之后,Alexei Starovoitov和Daniel Borkman等人对BPF进行了重新设计和实现,引入了eBPF(extended Berkeley Packet Filter),使其成为了一个更加通用的内核执行引擎。eBPF不仅限于网络数据包过滤,还可以用于各种内核跟踪、安全监控、网络功能、性能分析等广泛场景。

通过eBPF(extended Berkeley Packet Filter),我们编写程序来获取ICMP请求包与之关联的进程信息,包括但不限于以下几点:

  1. 进程ID (PID):可以获取发起ICMP请求的进程的唯一标识符。

  2. 进程名称:通常通过PID查找对应的可执行文件名,了解是哪个应用程序发起了ICMP请求。

  3. 命令行参数:进一步获取进程启动时使用的完整命令行,有助于识别进程的具体行为或目的。

  4. 用户ID和组ID:了解是哪个用户账户运行了发起ICMP请求的进程。

  5. 网络连接信息:包括源IP地址、目的IP地址、端口号(尽管ICMP没有端口号,但IP头信息依然重要)等网络层详情。

  6. 进程路径:进程的可执行文件在文件系统中的完整路径。

  7. 内存使用情况:虽然不是直接从ICMP请求获取,但可以通过eBPF关联到进程上下文后进一步查询。

  8. CPU和时间使用统计:可以收集进程消耗的CPU时间和执行时间的信息。

  9. 打开的文件描述符:列出进程当前打开的文件和网络套接字等资源。

由于并没有学过相关知识,所以这里使用 bpftrace 来利用 ebpf 帮助我们完成功能,这是一个高级的动态跟踪工具和域特定语言(Domain Specific Language, DSL),专为Linux系统设计,用于简化和加速系统及应用程序的监控及故障排查过程。它是基于eBPF(Extended Berkeley Packet Filter)技术构建的,允许用户编写脚本以收集内核和用户空间的运行时信息,而无需修改或重启系统

https://zh.wikipedia.org/wiki/BPF

0x03 找出恶意进程

其实核心思路很简单,icmp 协议的数据包没有端口的概念,当然icmp隧道可能会需要监听端口哈,但很难直接通过端口来判断,我们还是聚焦在 icmp 数据包对应的ip上

我们来处理 icmp 隧道,肯定是安全设备有告警了,那么我们需要获取到icmp隧道的对应的ip或者域名,如果是ip,我们后期在利用 ebpf 的过程中,筛选与该ip通信的icmp流量,之后查找pid 就好了

如果是域名,可能会涉及到cdn,我们可以通过修改系统 hosts 文件,将该域名指向到特定的ip,当然是存在的ip,之后进行过滤

首先,我们需要在要运行的服务器上安装 bpftrace ,以 Ubuntu 为例

`sudo apt update   sudo apt install bpftrace   `

我们使用以下 bfptrace 脚本监控与某个特定IP的所有请求,包括icmp,也包括dns

request_monitor.bt

`#!/usr/bin/bpftrace   #include <linux/skbuff.h>   #include <linux/ip.h>   #include <linux/socket.h>      kprobe:__dev_queue_xmit   {    @dev_queue_xmit[tid]=count();    @skb[tid]=(struct sk_buff *)arg0;   }      kprobe:__dev_queue_xmit   /@skb[tid]/   {    $skb = @skb[tid];    $iph = (struct iphdr *)($skb->head + $skb->network_header);    $sip = ntop(AF_INET, $iph->saddr);    $dip = ntop(AF_INET, $iph->daddr);          if ($iph->daddr == $1 || $iph->daddr == $2){     printf("[+] Found the request to %s \n", $dip);     printf("[-] pid=%d, thread_id=%d, comm=%s \n", pid,tid,comm);    }   }   `

这里涉及到一个问题,我们是希望查看特定IP的请求,但是直接将IP传递给 bpftrace 脚本比较困难,它不是很好处理,所以这里使用 shell 脚本进行辅助,主要是帮我们把 IP 转化为数字,并且同时转化为大端和小端序,也就是说我们会同时监听大端和小端的地址

request_monitor.sh

`#!/bin/bash      convert_ip_to_integers() {     local ip=$1     IFS='.' read -r a b c d <<< "$ip"          # 计算大端序 (big-endian)     be_ip_int=$((a << 24 | b << 16 | c << 8 | d))          # 计算小端序 (little-endian),需要颠倒字节顺序     le_ip_int=$((d << 24 | c << 16 | b << 8 | a))          echo "$be_ip_int $le_ip_int"   }      # IP地址参数   IP="$1"      # 调用函数,获取大端和小端的整数表示   read big_endian little_endian <<< $(convert_ip_to_integers "$IP")      # 假设BPFtrace脚本期望两个参数,分别对应大端和小端      echo "Start listening for the request to $IP"   echo ""   sudo ./request_monitor.bt $big_endian $little_endian      `

脚本参考

https://blog.csdn.net/native\_lee/article/details/124751325

0x04 ICMP 隧道排查演示

使用 pingtunnel 工具来模拟攻击者搭建的 icmp 隧道,服务端(攻击者)地址为 192.168.31.83

1. 服务端部署 icmp 隧道 server

`wget https://github.com/esrrhs/pingtunnel/releases/download/2.8/pingtunnel_linux_amd64.zip   unzip pingtunnel_linux_amd64.zip      # 启动服务端,设置 key 为 1234   ./pingtunnel -type server -key 1234   `

2. 受害端执行 icmp 隧道客户端

`wget https://github.com/esrrhs/pingtunnel/releases/download/2.8/pingtunnel_linux_amd64.zip   unzip pingtunnel_linux_amd64.zip      # 连接服务端   sudo ./pingtunnel -type client -l :4445 -s 192.168.31.83 -t 192.168.31.83:4444 -tcp 1 -key 1234   `

3. 应急人员上机处置

根据安全设备告警,得知存在 ICMP 隧道,连接地址为 192.168.31.83

通过 netstat 进行查看

果然看不到

因为当前服务器已经默认存在 bpftrace ,所以这里就先不重复安装了,将 request_monitor.shrequest_monitor.bt 复制到受害服务器上,给两个脚本赋予执行权限

`chmod +x request_monitor.sh   chmod +x request_monitor.bt   `

之后执行以下命令

`sudo ./request_monitor.sh 192.168.31.83   `

等待几秒后,开始监听

可以看到,发现了 pid 为 14990 的进程存在与 192.168.31.83 的通信,而且是多线程的,我们使用 ps -aux 验证一下是不是这样

可以看到, 14990 进程确实为 icmp 隧道的进程,成功找到icmp 隧道

发现进程id后剩下就没什么可说的了,常规处置流程了,至于DNS隧道就不掩饰了,大同小异

0x05 脚本下载

如果文中不好复制,可以通过以下 Github 地址获取

https://github.com/Just-Hack-For-Fun/request\_monitor

往期文章

有态度,不苟同

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2