华为云HIPS分析:进程行为篇
2022-12-1 11:36:19 Author: debugeeker(查看原文) 阅读量:6 收藏


华为云HIPS,名叫hostguard, 这篇是从hostguard的进程来分析这个产品

上一篇的链接:华为云HIPS分析:软件篇

[email protected]#ps -ef|grep hostguard|grep -v grep
root      1258     1  0  2019 ?        01:38:39 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log
root     10501  1258  0 Jun30 ?        00:12:59 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log

可以看到hostguard启动了两个同名进程,且1258号进程还是10501进程的父进程。

父进程

看一下1258号进程,先看一下它是否由docker还是systemd启动

[email protected]#cat /proc/1258/cgroup 
11:perf_event:/
10:memory:/system.slice/hostguard.service
9:devices:/system.slice/hostguard.service
8:blkio:/system.slice/hostguard.service
7:cpuset:/
6:hugetlb:/
5:net_prio,net_cls:/
4:cpuacct,cpu:/system.slice/hostguard.service
3:pids:/system.slice/hostguard.service
2:freezer:/
1:name=systemd:/system.slice/hostguard.service

可见它是由systemd启动的hostguard.service

再看启动参数和环境变量

[email protected]#cat /proc/1258/cmdline
/usr/local/hostguard/bin/hostguard^@-l^@/usr/local/hostguard/log^@
[email protected]#cat /proc/1258/environ 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin^@PWD=/^@LANG=en_US.UTF-8^@SHLVL=1^@_=/usr/local/hostguard/bin/hostguard^@

可见没什么有用信息,只是PATH环境变量调整了一下程序执行路径

再看它加载的so

[email protected]#cat /proc/1258/maps|awk '{print $6}'|sort|uniq

[heap]
[stack]
/usr/lib64/ld-2.17.so
/usr/lib64/libc-2.17.so
/usr/lib64/libdl-2.17.so
/usr/lib64/libm-2.17.so
/usr/lib64/libpthread-2.17.so
/usr/lib64/librt-2.17.so
/usr/local/hostguard/bin/hostguard
/usr/local/hostguard/bin/libagent.so
/usr/local/hostguard/bin/libbasecomm.so
/usr/local/hostguard/bin/libbaselogger.so
/usr/local/hostguard/bin/libbaseutils.so
/usr/local/hostguard/lib/libcrypto.so.1.0.0
/usr/local/hostguard/lib/libcurl.so.4.5.0
/usr/local/hostguard/lib/libgcc_s.so.1
/usr/local/hostguard/lib/libsecurec.so
/usr/local/hostguard/lib/libssl.so.1.0.0
/usr/local/hostguard/lib/libstdc_plus.so.6.0.14
[vdso]
[vsyscall]

可见,并没有加载一些功能so,说明这完全是一个daemon进程,可能是用来管控子进程的。

再看它的fd

[email protected]#ls -l /proc/1258/fd
total 0
lrwx------ 1 root root 64 Jun 11 15:41 0 -> /dev/null
lrwx------ 1 root root 64 Jun 11 15:41 1 -> /dev/null
lrwx------ 1 root root 64 Jun 11 15:41 2 -> /dev/null
lrwx------ 1 root root 64 Jun 11 15:41 3 -> /usr/local/hostguard/log/daemon.log

可见它确实是一个daemon进程。也就是说,hostguard的防护功能都放在子进程。

这种设计方式是非常好的。父进程的功能尽量简单,只做子进程的管控,一来父进程稳定,即使出问题也容易追溯,二来,如果子进程出了问题,父进程也容易恢复服务。

子进程

由于105011258的子进程,那么cgroup不用分析了。只要分析其它的。

分析启动参数和环境变量,一般父进程在启动子进程时,有可能会设置启动参数和改变环境变量,一般集中在PATH, LD_LIBRARY_PATH之类。

软件打桩技术,一般是启动子进程执行被分析程序,通过改变LD_LIBRARY_PATH这个环境变量,让被分析程序加载指定so。这些指定so会定义不少和libc.so同名的函数。各种性能分析软件就是使用这种技术。

[email protected]#cat /proc/10501/cmdline 
/usr/local/hostguard/bin/hostguard^@-l^@/usr/local/hostguard/log^@
[email protected]#cat /proc/10501/environ 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin^@PWD=/^@LANG=en_US.UTF-8^@SHLVL=1^@_=/usr/local/hostguard/bin/hostguard^@

可见父进程并没有对子进程进行打桩。

看一下子进程加载的so

[email protected]#cat /proc/10501/maps|awk '{print $6}'|sort|uniq

[heap]
[stack]
/usr/lib64/ld-2.17.so
/usr/lib64/libc-2.17.so
/usr/lib64/libcrypt-2.17.so
/usr/lib64/libdl-2.17.so
/usr/lib64/libfreebl3.so
/usr/lib64/libfreeblpriv3.so
/usr/lib64/libm-2.17.so
/usr/lib64/libnss_files-2.17.so
/usr/lib64/libpthread-2.17.so
/usr/lib64/librt-2.17.so
/usr/local/hostguard/bin/hostguard
/usr/local/hostguard/bin/libagent.so
/usr/local/hostguard/bin/libbasecomm.so
/usr/local/hostguard/bin/libbaselogger.so
/usr/local/hostguard/bin/libbaseutils.so
/usr/local/hostguard/bin/libmodargoseye.so
/usr/local/hostguard/bin/libmoddetconf.so
/usr/local/hostguard/bin/libmodfastscan.so
/usr/local/hostguard/bin/libmodfilemon.so
/usr/local/hostguard/bin/libmodiso.so
/usr/local/hostguard/bin/libmodlogin.so
/usr/local/hostguard/bin/libmodprocmon.so
/usr/local/hostguard/bin/libmodpuppetdet.so
/usr/local/hostguard/bin/libmodpwd.so
/usr/local/hostguard/bin/libmodwebcms.so
/usr/local/hostguard/bin/libmodwhitelist.so
/usr/local/hostguard/bin/libmodwshell.so
/usr/local/hostguard/lib/libcrypto.so.1.0.0
/usr/local/hostguard/lib/libcurl.so.4.5.0
/usr/local/hostguard/lib/libgcc_s.so.1
/usr/local/hostguard/lib/libmagic.so.1.0.0
/usr/local/hostguard/lib/libsecurec.so
/usr/local/hostguard/lib/libssl.so.1.0.0
/usr/local/hostguard/lib/libstdc_plus.so.6.0.14
/usr/local/hostguard/lib/libyara.so.3.4.0
/usr/local/hostguard/lib/libz.so.1.2.11
[vdso]
[vsyscall]

可见,确实是子进程加载了各种功能模块,也就是检测功能都放在子进程里。

这种设计有很大缺陷。因为HIPS有实时监控功能和定时扫描功能(用于各种基线)。把所有功能放在一个进程里,就会出现这样的情况:当在进行定时扫描时,刚好有大量事件出现,这时候实时监控功能也会占用不少资源,导致整个进程达到预定的资源配额时,会导致进程被重启,从而中断扫描,使得一些基线检查无法完成。所以,最好还是把进程拆分,每个进程完成一种功能。

再看打开的fd

[email protected]#ls -l /proc/10501/fd
total 0
lrwx------ 1 root root 64 Jun 30 14:40 0 -> /dev/null
lrwx------ 1 root root 64 Jun 30 14:40 1 -> /dev/null
lr-x------ 1 root root 64 Jun 30 14:40 10 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 11 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 12 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 13 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 14 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 15 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 16 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 17 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 18 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 19 -> anon_inode:inotify
lrwx------ 1 root root 64 Jun 30 14:40 2 -> /dev/null
lr-x------ 1 root root 64 Jun 30 14:40 20 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 21 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 22 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 23 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 24 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 25 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 26 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 27 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 28 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 29 -> anon_inode:inotify
lrwx------ 1 root root 64 Jun 30 14:40 3 -> /usr/local/hostguard/log/hostguard.log
lr-x------ 1 root root 64 Jun 30 14:40 30 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 31 -> anon_inode:inotify
lrwx------ 1 root root 64 Jun 30 14:40 32 -> socket:[2797256217]
lr-x------ 1 root root 64 Jun 30 14:40 33 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 18:46 34 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jul  2 21:31 35 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jun 30 14:41 36 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jun 30 23:06 37 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jun 30 23:06 38 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jul  3 21:50 39 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jun 30 14:40 4 -> anon_inode:inotify
lr-x------ 1 root root 64 Jul  1 23:06 40 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jul  4 21:51 41 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jul  3 03:50 42 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jul  5 11:16 43 -> /proc/71500/net/tcp
lr-x------ 1 root root 64 Jul  3 23:06 44 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jun 30 14:40 5 -> anon_inode:inotify
lrwx------ 1 root root 64 Jul  2 18:43 6 -> socket:[2808807671]
lr-x------ 1 root root 64 Jun 30 14:40 7 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 8 -> anon_inode:inotify
lr-x------ 1 root root 64 Jun 30 14:40 9 -> anon_inode:inotify

满屏的anon_inode:inotify就说明hostguard在实时监控文件变动,这么多的inotify实例,会不会导致内核内存占用过多,毕竟一个inotify监控事件结构体是300-500字节。

而这些

lr-x------ 1 root root 64 Jun 30 18:46 34 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jul  2 21:31 35 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jun 30 14:41 36 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jun 30 23:06 37 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jun 30 23:06 38 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jul  3 21:50 39 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jul  1 23:06 40 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jul  4 21:51 41 -> /usr/local/hostguard/benchmarks/ssh.zip
lr-x------ 1 root root 64 Jul  3 03:50 42 -> /usr/local/hostguard/benchmarks/tomcat.zip
lr-x------ 1 root root 64 Jul  3 23:06 44 -> /usr/local/hostguard/benchmarks/tomcat.zip

说明正在进行一些服务配置的基线检查。但配置脚本重复加载了。之前调研时,也遇到打开了280个fd,大部分是这些配置脚本,一开始以为是句柄泄露了,后来回落了。在这一块,hostguard需要好好审计一下代码,毕竟这5个配置脚本压缩包大小有297K,就算不解压,如果达到50份,也有14M,再加上其它任务,可能就导致hostguard达到内存配额150M,从而被重启掉。

再看fd里面的两个socket

lrwx------ 1 root root 64 Jun 30 14:40 32 -> socket:[2797256217]
lrwx------ 1 root root 64 Jul  2 18:43 6 -> socket:[2808807671]

看一下2808807671这个,第6个fd

[email protected]#grep -rIn 2808807671 /proc/10501/net/
/proc/10501/net/tcp:73:  71: 0201000A:ED02 27007D64:01BB 01 00000000:00000000 00:00000000 00000000     0        0 2808807671 1 ffff880037394d80 20 4 0 10 9          

可见,它是一个TCP socket,是对应这个

[email protected]#netstat -anp4|grep hostguard
tcp        0      0 10.0.1.2:60674          100.125.0.39:443        ESTABLISHED 10501/hostguard    

这说明它是和管理端相连。

再看一下第32个fd,2797256217

[email protected]#grep -rIn 2797256217 /proc/10501/net/
/proc/10501/net/netlink:10:ffff880227ba4000 11  10501  00000001 0        0        0 2        721841   2797256217

说明它是netlink socket

根据netlink文件的格式

sk       Eth Pid    Groups   Rmem     Wmem     Dump     Locks     Drops     Inode

可见这个netlink socket的信息是

  • sk: ffff880227ba4000
  • Eth: 11
  • Pid: 10501
  • Groups: 00000001
  • Rmem: 0
  • Wmem: 0
  • Dump: 0
  • Locks: 2
  • Drops: 721841
  • Inode: 2797256217

根据内核代码net/netlink/af_netlink.c:

static int netlink_native_seq_show(struct seq_file *seq, void *v)
{
 if (v == SEQ_START_TOKEN) {
  seq_puts(seq,
    "sk               Eth Pid        Groups   "
    "Rmem     Wmem     Dump  Locks    Drops    Inode\n");
 } else {
  struct sock *s = v;
  struct netlink_sock *nlk = nlk_sk(s);

  seq_printf(seq, "%pK %-3d %-10u %08x %-8d %-8d %-5d %-8d %-8u %-8lu\n",
      s,
      s->sk_protocol,
      nlk->portid,
      nlk->groups ? (u32)nlk->groups[0] : 0,
      sk_rmem_alloc_get(s),
      sk_wmem_alloc_get(s),
      nlk->cb_running,
      refcount_read(&s->sk_refcnt),
      atomic_read(&s->sk_drops),
      sock_i_ino(s)
   );

 }
 return 0;
}

可知sk_protocol是11,那么11是哪个值呢?

根据/usr/include/linux/netlink.h的定义

#define NETLINK_ROUTE  0 /* Routing/device hook    */
#define NETLINK_UNUSED  1 /* Unused number    */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols  */
#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue  */
#define NETLINK_SOCK_DIAG 4 /* socket monitoring    */
#define NETLINK_NFLOG  5 /* netfilter/iptables ULOG */
#define NETLINK_XFRM  6 /* ipsec */
#define NETLINK_SELINUX  7 /* SELinux event notifications */
#define NETLINK_ISCSI  8 /* Open-iSCSI */
#define NETLINK_AUDIT  9 /* auditing */
#define NETLINK_FIB_LOOKUP 10 
#define NETLINK_CONNECTOR 11
#define NETLINK_NETFILTER 12 /* netfilter subsystem */
#define NETLINK_IP6_FW  13
#define NETLINK_DNRTMSG  14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
#define NETLINK_GENERIC  16

可知,它这个值是NETLINK_CONNECTOR,说明是一个Kernel connector

Kernel connector:新的基于 netlink 的用户空间 <-> 内核空间容易使用通讯模块。

既然已经知道是Kernel connector,那么groups的定义就从/usr/include/linux/connector.h

define CN_IDX_PROC   0x1
#define CN_VAL_PROC   0x1
#define CN_IDX_CIFS   0x2
#define CN_VAL_CIFS                     0x1
#define CN_W1_IDX   0x3 /* w1 communication */
#define CN_W1_VAL   0x1
#define CN_IDX_V86D   0x4
#define CN_VAL_V86D_UVESAFB  0x1
#define CN_IDX_BB   0x5 /* BlackBoard, from the TSP GPL sampling framework */
#define CN_DST_IDX   0x6
#define CN_DST_VAL   0x1
#define CN_IDX_DM   0x7 /* Device Mapper */
#define CN_VAL_DM_USERSPACE_LOG  0x1
#define CN_IDX_DRBD   0x8
#define CN_VAL_DRBD   0x1
#define CN_KVP_IDX   0x9 /* HyperV KVP */
#define CN_KVP_VAL   0x1 /* queries from the kernel */
#define CN_VSS_IDX   0xA     /* HyperV VSS */
#define CN_VSS_VAL   0x1     /* queries from the kernel */

从groups的值为1,可知hostguard使用netlink从内核接收实时进程创建,退出的信息,也就是hostguard有做进程实时监控功能。

看进程的防护能力

杀掉10501进程,看看会如何?

[email protected]#ps aux|grep hostguard|grep -v "grep"
root      1258  0.0  0.0  41000  1512 ?        Ss    2019  99:02 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log
root     10501  0.4  0.2 1229132 17608 ?       Sl   Jun30  29:44 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log
[email protected]#kill -9 10501
[email protected]#ps aux|grep hostguard|grep -v "grep"
root      1258  0.0  0.0  41000  1512 ?        Ss    2019  99:02 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log
root     55611 25.0  0.1 636692 10920 ?        Sl   16:46   0:00 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log

可见重新创建了55611子进程。

如果杀掉1258进程,就没有再创建进程了,只能重启服务了。

[email protected]#kill -9 1258
[email protected]#ps aux|grep hostguard|grep -v "grep"
root     55611  1.7  0.1 1226520 13796 ?       Sl   16:46   0:02 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log
[email protected]#ps aux|grep hostguard|grep -v "grep"
root     55611  1.7  0.1 1226516 13796 ?       Sl   16:46   0:02 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log
[email protected]#ps aux|grep hostguard|grep -v "grep"
root     55611  1.7  0.1 1226520 13796 ?       Sl   16:46   0:02 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log
[email protected]#ps aux|grep hostguard|grep -v "grep"
root     55611  1.6  0.1 1226516 13804 ?       Sl   16:46   0:02 /usr/local/hostguard/bin/hostguard -l /usr/local/hostguard/log

从这一点,说明hostguard并没有对服务的防护能力

结论

hostguard单从进程行为来看,有如下能力:

  1. 父进程对子进程的防护能力。但没有自身服务防护能力。
  2. 使用inotify进行实时文件监控
  3. 使用netlink进行实时进程事件监控
  4. 从上面数据可以看到,cpu最高到25%,内存在0.2%左右,说明它有做资源控制。

=========================================

暗号:7ae7c


文章来源: http://mp.weixin.qq.com/s?__biz=MzU4NjY0NTExNA==&mid=2247486914&idx=1&sn=75de8f24369d860877e39902afc9309a&chksm=fdf966d7ca8eefc11dbd084f9c330dc3d94d9aa44107d1a078c491ef93f2038876c0aec56048#rd
如有侵权请联系:admin#unsafe.sh