Linux主机入侵外连行为检测

admin 2023年3月5日16:12:22评论32 views字数 11186阅读37分17秒阅读模式

主机入侵检测系统系列:这一篇讲述检测外连行为的原理和技术,可统一检测宿主机和docker子机

一台主机入侵后,入侵者往往会把数据发送出去或启动reverse shell。一般在IDC的出口防火墙都会有检测异常外连行为,可能由于中间有NAT,并不一定知道是哪台机器过来,但即使是知道哪台机器过来的,也不知道是该台机器哪个程序发起的外连行为。

通常的操作,都是用netstat命令来获取

[root@bogon-agent test]# netstat -anp4
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:42485         0.0.0.0:*               LISTEN      33041/node          
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1640/sshd           
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1885/master         
tcp        0      0 127.0.0.1:55622         127.0.0.1:42485         ESTABLISHED 25101/sshd: buckxu@ 
tcp        0      0 127.0.0.1:42485         127.0.0.1:50352         ESTABLISHED 33041/node          
tcp        0      0 127.0.0.1:42485         127.0.0.1:55622         ESTABLISHED 25171/node          
tcp        0      0 127.0.0.1:50354         127.0.0.1:42485         ESTABLISHED 128902/sshd: buckxu 
tcp        0      0 192.168.190.129:45782   192.168.190.128:1514    ESTABLISHED 2109/ossec-agentd   
tcp        0      0 127.0.0.1:50352         127.0.0.1:42485         ESTABLISHED 128902/sshd: buckxu 
tcp        0      0 192.168.190.129:22      192.168.190.1:62331     ESTABLISHED 25087/sshd: buckxu  
tcp        0      0 127.0.0.1:42485         127.0.0.1:50354         ESTABLISHED 128969/node         
tcp        0      0 127.0.0.1:42485         127.0.0.1:55620         ESTABLISHED 33041/node          
tcp        0      0 192.168.190.129:22      192.168.190.1:52429     ESTABLISHED 128898/sshd: buckxu 
tcp        0      0 127.0.0.1:55620         127.0.0.1:42485         ESTABLISHED 25101/sshd: buckxu@ 
udp        0      0 0.0.0.0:68              0.0.0.0:*                           103880/dhclient   

但如果放在HIDS(主机入侵检测系统)实现,就不可能调用命令,原因如下:

  1. 有些Linux机器可能没有安装netstat命令
  2. 即使有netstat命令,也可能由于之前的操作,导致netstat运行时依赖的so库缺失或符号缺失,导致无法执行这个命令
  3. netstat命令执行有异常,变成僵尸进程
  4. netstat命令在宿主机是没办法查到docker里的外连行为

按照Unix哲学一切皆文件,像端口和进程信息这些内容都可以从/proc文件系统下找到,所以HIDS是会/proc获取这些信息。

下面拿上面命令结果的2109/node来做例子展示这种手段。

  • 由于一个socket在Linux里是一个fd,先看一下/proc/2109/fd的内容

    [root@bogon-agent ~]# ls -l /proc/2109/fd 
    total 0
    lrwx------. 1 root root 64 Jan  4 18:35 0 -> /dev/null
    lrwx------. 1 root root 64 Jan  4 18:35 1 -> /dev/null
    lrwx------. 1 root root 64 Jan  4 18:35 2 -> /dev/null
    lrwx------. 1 root root 64 Jan  4 18:35 3 -> socket:[26069]
    lr-x------. 1 root root 64 Jan  4 18:35 4 -> /dev/urandom
    lrwx------. 1 root root 64 Jan  4 18:35 5 -> /var/ossec/queue/rids/005
    lrwx------. 1 root root 64 Jan  4 18:35 6 -> /var/ossec/queue/rids/sender_counter
    lrwx------. 1 root root 64 Jan  4 18:35 7 -> socket:[18173675]
    lrwx------. 1 root root 64 Jan  4 18:35 8 -> socket:[2986416]
  • 取这一行

    lrwx------. 1 root root 64 Jan  4 18:35 7 -> socket:[18173675]

    其中2969198inode。到/proc/33041/net找一下这个inode是在哪个文件有使用

    [root@bogon-agent ~]# grep -rIn "18173675" /proc/2109/net
    /proc/2109/net/tcp:9:   7: 81BEA8C0:B2D6 80BEA8C0:05EA 01 00000000:00000000 00:00000000 00000000   983        0 18173675 1 ffff9259346e3640 20 4 30 10 7     
  • 看一下/proc/2109/net/tcp的内容

    [root@bogon-agent ~]# cat /proc/2109/net/tcp
    sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode
    0: 0100007F:A5F5 00000000:0000 0A 00000000:00000000 00:00000000 00000000  1000        0 2969198 1 ffff92593308be00 100 0 0 10 0                   
    1: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 24908 1 ffff925934638000 100 0 0 10 0                     
    2: 0100007F:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 25073 1 ffff9259346387c0 100 0 0 10 0                     
    3: 0100007F:D946 0100007F:A5F5 01 00000000:00000000 00:00000000 00000000  1000        0 28151168 1 ffff92593308b640 20 4 30 3 2                   
    4: 0100007F:A5F5 0100007F:C4B0 01 00000000:00000000 00:00000000 00000000  1000        0 4419751 1 ffff9259346e3e00 20 4 28 10 12                  
    5: 0100007F:A5F5 0100007F:D946 01 00000000:00000000 00:00000000 00000000  1000        0 28146298 1 ffff92593308f440 21 4 28 10 -1                 
    6: 0100007F:C4B2 0100007F:A5F5 01 00000000:00000000 00:00000000 00000000  1000        0 4418745 1 ffff9259346e45c0 20 4 28 3 2                    
    7: 81BEA8C0:B2D6 80BEA8C0:05EA 01 00000000:00000000 00:00000000 00000000   983        0 18173675 1 ffff9259346e3640 20 4 30 10 7                  
    8: 0100007F:C4B0 0100007F:A5F5 01 00000000:00000000 00:00000000 00000000  1000        0 4418744 1 ffff9259346e2e80 20 4 30 4 4                    
    9: 81BEA8C0:0016 01BEA8C0:F37B 01 0000004C:00000000 01:00000015 00000000     0        0 28146223 4 ffff9259346e7440 21 4 31 10 663                
    10: 0100007F:A5F5 0100007F:C4B2 01 00000000:00000000 00:00000000 00000000  1000        0 4419752 1 ffff9259346e4d80 20 4 30 10 7                   
    11: 0100007F:A5F5 0100007F:D944 01 00000000:00000000 00:00000000 00000000  1000        0 28146297 3 ffff9259330887c0 20 4 31 10 25                 
    12: 81BEA8C0:0016 01BEA8C0:CCCD 01 00000000:00000000 02:0004A056 00000000     0        0 4418688 2 ffff9259346e1f00 23 4 30 10 579                 
    13: 0100007F:D944 0100007F:A5F5 01 00000000:00000000 00:00000000 00000000  1000        0 28151167 2 ffff92593308ae80 20 4 30 10 -1    
  • 由于每个/proc/<pid>/net/tcp文件的格式和/proc/net/tcp是一样的,按照Linux内核文档Documentation/networking/proc_net_tcp.txt的内容

    This document describes the interfaces /proc/net/tcp and /proc/net/tcp6.
    Note that these interfaces are deprecated in favor of tcp_diag.

    These /proc interfaces provide information about currently active TCP
    connections, and are implemented by tcp4_seq_show() in net/ipv4/tcp_ipv4.c
    and tcp6_seq_show() in net/ipv6/tcp_ipv6.c, respectively.

    It will first list all listening TCP sockets, and next list all established
    TCP connections. A typical entry of /proc/net/tcp would look like this (split
    up into 3 parts because of the length of the line):

    46: 010310AC:9C4C 030310AC:1770 01
    | | | | | |--> connection state
    | | | | |------> remote TCP port number
    | | | |-------------> remote IPv4 address
    | | |--------------------> local TCP port number
    | |---------------------------> local IPv4 address
    |----------------------------------> number of entry

    00000150:00000000 01:00000019 00000000
    | | | | |--> number of unrecovered RTO timeouts
    | | | |----------> number of jiffies until timer expires
    | | |----------------> timer_active (see below)
    | |----------------------> receive-queue
    |-------------------------------> transmit-queue

    1000 0 54165785 4 cd1e6040 25 4 27 3 -1
    | | | | | | | | | |--> slow start size threshold,
    | | | | | | | | | or -1 if the threshold
    | | | | | | | | | is >= 0xFFFF
    | | | | | | | | |----> sending congestion window
    | | | | | | | |-------> (ack.quick<<1)|ack.pingpong
    | | | | | | |---------> Predicted tick of soft clock
    | | | | | | (delayed ACK control data)
    | | | | | |------------> retransmit timeout
    | | | | |------------------> location of socket in memory
    | | | |-----------------------> socket reference count
    | | |-----------------------------> inode
    | |----------------------------------> unanswered 0-window probes
    |---------------------------------------------> uid

    timer_active:
    0 no timer is pending
    1 retransmit-timer is pending
    2 another timer (e.g. delayed ack or keepalive) is pending
    3 this is a socket in TIME_WAIT state. Not all fields will contain
    data (or even exist)
    4 zero window probe timer is pending

    上面说明这个socket的信息如下:

    根据Linux内核代码net/ipv4/tcp_ipv4.ctcp4_seq_show实现, IP地址还是网络字节序,而端口则已经转为本机字节序

    根据Linux内核代码include/net/tcp_states.h的枚举定义,socket状态的定义如下

    enum {
    TCP_ESTABLISHED = 1,
    TCP_SYN_SENT,
    TCP_SYN_RECV,
    TCP_FIN_WAIT1,
    TCP_FIN_WAIT2,
    TCP_TIME_WAIT,
    TCP_CLOSE,
    TCP_CLOSE_WAIT,
    TCP_LAST_ACK,
    TCP_LISTEN,
    TCP_CLOSING, /* Now a valid state */

    TCP_MAX_STATES /* Leave at the end! */
    };

    从上面来看,2109这个进程通过本机地址192.168.190.129的45782端口连接远端192.168.190.128的端口1514。那么在HIDS里实现,就可以定时去扫描/proc/<pid>/fd/proc/<pid>/net/tcp,就可以获取到哪个进程启动了连接到哪些机器,再对远程IP进行筛选,就知道是否有外连行为。

    通过这种技术,也可以监控高危端口开启,大量socket time_wait堆积的情况,检测发送队列和接收队列是否有数据包堆积。

    用同样方式在unix socket上,还可以得到进程的IPC连接

    • 本地地址是192.168.190.129:45782 ,对应数据(81BEA8C0:B2D6)
    • 远程地址是192.168.190.128:1514, 对应数据(80BEA8C0:05EA)
    • 状态是已连接,对应数据01
    • 发送队列和接收队列的堵塞情况均为0,对应数据00000000:00000000
    • 没有定时器,距离定时的飞秒还有0,对应数据00:00000000
    • 重传的次数是0
    • uid是983
    • 未回答的0窗口探测为0
    • inode是18173675
    • 引用次数是1,说明只是本机一个进程使用

Docker情况

上面技术能否检测Docker内部的外连行为,答案是可以的。

  • 看一下docker的运行情况,有一个docker在运行,ID是b0d8c7be723f

    [root@bogon-agent ~]# docker ps
    CONTAINER ID   IMAGE     COMMAND                  CREATED        STATUS      PORTS     NAMES
    b0d8c7be723f   nginx     "/docker-entrypoint.…"   3 months ago   Up 7 days   80/tcp    great_hawking
  • 看一下b0d8c7be723f运行的进程,可以看到运行了nginx, pid分别为78299, 78350

    root@bogon-agent ~]# docker top b0d8c7be723f
    UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
    root                78299               78280               0                   2020                ?                   00:00:00            nginx: master process nginx -g daemon off;
    101                 78350               78299               0                   2020                ?                   00:00:00            nginx: worker process
  • netstat命令却是看不到nginx监听在80端口的, 怎么办呢?

    [root@bogon-agent ~]# netstat -anp4
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
    tcp        0      0 127.0.0.1:42485         0.0.0.0:*               LISTEN      33041/node          
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1640/sshd           
    tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      1885/master         
    tcp        0      0 127.0.0.1:55622         127.0.0.1:42485         ESTABLISHED 25101/sshd: buckxu@ 
    tcp        0      0 127.0.0.1:42485         127.0.0.1:50352         ESTABLISHED 33041/node          
    tcp        0      0 127.0.0.1:42485         127.0.0.1:55622         ESTABLISHED 25171/node          
    tcp        0      0 127.0.0.1:50354         127.0.0.1:42485         ESTABLISHED 128902/sshd: buckxu 
    tcp        0      0 192.168.190.129:45782   192.168.190.128:1514    ESTABLISHED 2109/ossec-agentd   
    tcp        0      0 127.0.0.1:50352         127.0.0.1:42485         ESTABLISHED 128902/sshd: buckxu 
    tcp        0      0 192.168.190.129:22      192.168.190.1:62331     ESTABLISHED 25087/sshd: buckxu  
    tcp        0      0 127.0.0.1:42485         127.0.0.1:50354         ESTABLISHED 128969/node         
    tcp        0      0 127.0.0.1:42485         127.0.0.1:55620         ESTABLISHED 33041/node          
    tcp        0      0 192.168.190.129:22      192.168.190.1:52429     ESTABLISHED 128898/sshd: buckxu 
    tcp        0      0 127.0.0.1:55620         127.0.0.1:42485         ESTABLISHED 25101/sshd: buckxu@ 
    udp        0      0 0.0.0.0:68              0.0.0.0:*                           103880/dhclient     
  • 根据Linux命名空间的机制,在物理机上是可以看到docker里的进程,选择78350为例

    [root@bogon-agent ~]# ls -l /proc/78350/exe 
    lrwxrwxrwx. 1 101 101 0 Jan  4 16:43 /proc/78350/exe -> /usr/sbin/nginx
  • 通过查看/proc/78350/net/tcp文件,是可以看到这个进程监听在80端口。可见,这种手段也是可以应用于docker场景

    [root@bogon-agent ~]# cat /proc/78350/net/tcp
    sl  local_address rem_address   st tx_queue rx_queue tr tm->when retrnsmt   uid  timeout inode                                                     
    0: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 11678003 1 ffff92593463cd80 100 0 0 10 0     


Linux主机入侵外连行为检测

原文始发于微信公众号(哆啦安全):Linux主机入侵外连行为检测

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月5日16:12:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Linux主机入侵外连行为检测https://cn-sec.com/archives/1588381.html

发表评论

匿名网友 填写信息