如何结束和暂停agent进程
问题背景
就像 如何避免文件上报-制作大文件 说的,hids agent会上报很多信息,安全防护策略也是围绕”agent上报的信息”制定的。
那如果攻击者”结束、暂停agent进程”,导致agent功能废掉,是不是就能够绕过hids的防护呢?
研究过程中,我发现并不能轻易地结束agent进程;”结束和暂停agent进程”会带来”心跳失联”的异常特征,可能引起”运营人员”的注意从而导致攻击行为暴露。
本文主要讨论以下问题:
- 怎么结束agent进程?
- 怎么暂停agent进程?
- “心跳失联”
结束agent进程
怎么结束agent进程?
在linux上执行
kill -SIGKILL 进程号
是一定可以结束进程的,因为 SIGKILL信号不能被忽略或者做其他处理。但是我们杀掉hids agent进程后,agent进程会自动重启。
怎么实现”挂掉自动重启”?
经过调研,”挂掉自动重启”机制在linux最常见的实现方式包括:
通过 systemd、supervisord 等实现
crond:通过计划任务
watchdog
字节hids文档 推荐的也是”systemd”和”crond”这两种方式。
有对supervisord、systemd实现原理感兴趣的,可以看最后一节。
怎么结束被systemd、supervisord管理的进程?
supervisord和systemd等管理的进程可以通过”supervisorctl”和”systemctl”等命令关掉。
这两命令实际也是通过”本地socket通信”告诉supervisord和systemd结束进程,所以当没有办法使用”supervisorctl”和”systemctl”命令时,也可以编写程序直接和”本地socket文件”通信。
暂停agent进程
怎么暂停agent进程?
向进程发送SIGSTOP、SIGTSTP、SIGTTIN等信号都可能暂停进程,推荐用SIGSTOP信号,原因是进程收到其他信号还能忽略,收到SIGSTOP信号却只能暂停进程。
这个结论可以在
man 7 signal
看到The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
“暂停的agent进程”是否会被自动重启或者恢复运行状态?
这里还存在一个小问题:当子进程被暂停或者结束时,父进程是可以收到SIGCHLD信号的。那systemd遇到子进程暂停时,会不会重启进程?
经过测试和源码对比,我的结论是:systemd不会。
测试某hids
经过对某hids做测试,发现stop状态的agent进程会被恢复成运行状态。
agent进程的父进程的父进程才是systemd,所以估计是agent父进程收到SIGCHLD信号后向agent进程发送了SIGCONT信号恢复运行状态。
当把hids所有的agent进程都暂停后,符合预期:所有agent进程一直被暂停。
“心跳失联”的问题
“心跳失联”是什么?
正常情况下,agent按照一定频率会发送”心跳包”告诉server自己存活。
如果”结束和暂停agent进程”,就会影响到”心跳包”的发送。进而server端是可以感知到agent异常的。
这种异常可能引起”运营人员”的注意从而导致攻击行为暴露。
怎么解决”心跳失联”的问题?
凭空想象的一种解决方法:恶意样本 先暂停agent进程,等到恶意行为完成后,再恢复agent进程。
这样心跳也存在,也有可能绕过hids防护。
systemd是怎么知道”进程挂掉”?
先说我验证的结论:
- systemd为sigchild信号注册了一个处理函数,函数内部调用waitid处理退出的子进程。
- 当systemd管理的进程退出时,systemd进程会收到sigchild信号,进而跳转到处理函数。
从systemd源码可以看到manager_setup_sigchld_event_source函数就是”sigchild信号的处理函数”。
如果systemd进程号为1,也可以通过strace -p 1
来验证结论:
结束systemd管理的进程时(下面例子中是83206号进程),可以看到waitid系统调用
1 | waitid(P_ALL, 0, {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=83206, si_uid=0, si_status=SIGKILL, si_utime=0, si_stime=0}, WNOHANG|WEXITED|WNOWAIT, NULL) = 0 |
supervisord和systemd有点类似,不一样的是supervisord似乎只用wait等系统调用,来判断子进程是否已经退出。
1 | [root@instance-fj5pftdp ~]# ps aux|grep supervi |
总结
- “结束进程”需要考虑到”进程挂掉重启”的场景
- “暂停进程”需要考虑到”父进程恢复进程状态”的场景
本文提到的手段没有在真实的对抗中实践过,仅仅是我自己的研究,欢迎与我交流。