張ボー、網易シニア情報セキュリティエンジニア:著者について。
0x00の概要
攻撃の大半は、プロセスを提示する攻撃者の道であるため、侵入検知の過程では、プロセス作成の監視は、私たちはすぐに攻撃を見つけやすくするために作成された新しいプロセスに関する情報にとてもタイムリーなアクセスが不可欠です行動。
この記事では、創造のプロセスを監視し、その原則、デモ、使用の条件と長所と短所を含めての一般的な方法のいくつかを説明しています。性急な製図、間違いや欠点であれば、だけでなく、すべての人の批判を願っています。
0x01の一般的な方法
今のところ、情報のプロセスに共通のアクセスは、次の4つの方法を作成しました:
- プリロードので、
- NetLinkのコネクタ
- 監査
- システムコールフック
ここで我々が持っている原理を、デモでは、使用して長所と短所の条件は、これらの4つの方法を見て。
0×02だから、プリロード
原則
最初はあなたと2時の基本を紹介しました:
実施プロセスに関する1.Linux実行可能プログラムのほとんどは動的にリンクされ、一般的に使用される機能は、例えば、execve
このダイナミックリンクライブラリlibc.soに実装されています。
2.Linux予圧が優先負荷の定義ダイナミックリンクライブラリを可能にするメカニズムを提供するので、ユーザーフレンドリーな機能を選択的に異なるダイナミック・リンク・ライブラリをロードするための同じです。
これら2点の組み合わせを得ることは困難ではない、我々はlibc.so予圧ようにすることによって無効にすることができexecve
、他の機能を作成するプロセスを監視します。
デモ
ここでは、簡単なデモを実装する必要があります。
1.次のようにファイルhook.cを作成し、読み取ります。
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
typedef ssize_t (*execve_func_t)(const char* filename, char* const argv[], char* const envp[]);
static execve_func_t old_execve = NULL;
int execve(const char* filename, char* const argv[], char* const envp[]) {
printf("Running hook\n");
printf("Program executed: %s\n", filename);
old_execve = dlsym(RTLD_NEXT, "execve");
return old_execve(filename, argv, envp);
}
本書の主要部分は、再定義することでexecve
、機能を元にexecve
、実行する前に、実行可能ファイルの名前を印刷します。
2.ダイナミックリンクライブラリを生成します。gcc hook.c-fPIC-shared-o hook.so
3.プリロードとして登録するには、上記生成されたダイナミックリンクライブラリ:echo'/path/to/hook.so'>/etc/ld.so.preload
4.終了し、現在のシェルと再度ログインが(下記の理由を話す)、私たちが書いたコードが実行された参照するためのコマンドを実行します。
使用条件
このメソッドは、(root権限が侵入監視プログラムが必要とされないために、いくつかの方法は、デフォルトのroot権限での背後にもある)root権限を持っているためにどのような条件、制限はしていません。
長所と短所
利点
- 軽量、唯一の機能コードライブラリを修正し、カーネルではない相互作用ありません。
短所
使用方法の第4ステップでは、と私たちは疑問であってもよい:彼らはそれの効果を見ることができる前に、なぜ、シェルを再取得しなければなりませんか?(現在のシェルで実行され、実際に実行したコマンドがためですexecve
)、実際に、このようなbashのは、bashや必要なダイナミックリンクライブラリとして現在のシェルの実行可能プログラムは、操作の開始時に特定されたされ、我々はフォローアップを追加しますので、プリロードは、プリロードの作成が影響を受けることになります後にのみ、プリロード・プロセスを追加し、現在のbashには影響しません。これは、このメソッドの最初の欠点を描画します:
- 他のアプリケーションの前に開始し、インストールプロセスを完了するために、可能な限りとしてのみ、エージェントが早いほど良いインストールの検出を必要とプリロード、後に作成されたプロセスに影響を与えます。
さらに、次のような欠点があります。
- 静的にリンクされたプログラムを監視することはできません。現時点では、環境への依存を低減するためにいくつかのワーム、トロイの木馬は、静的リンクされている共有ライブラリをロードしません、この場合は、この監視方法は無効となります。
- 簡単に攻撃者によって発見され、改ざん:現時点では、いくつかのワーム、トロイの木馬は、この場合は失敗する方法を監視し、マシン、その持続的な制御を容易にするために、/etc/ld.so.preloadへの扉を書き戻します。
- 攻撃者がすることができます
int80h
直接libcのコール迂回システムを呼び出して、この場合は、この監視方法は失敗します。
0x03をするNetlinkコネクタ
原則
するNetlinkコネクタを導入する前に、最初にするNetlinkが何であるかを全く見ての、するNetlinkは、IPCは、カーネルとユーザーモードプロセスとユーザーモードプロセス間の通信に使用されていること、家族のソケット(ソケットファミリー)で、我々は使用ss
コマンドを通じでありますNetLinkのは、情報を得るために、カーネルと通信します。
コネクタするNetlinkするNetlinkは、それがネットリンクプロトコル番号であるNETLINK_CONNECTOR
コードである、https://github.com/torvalds/linux/tree/master/drivers/connectorれconnectors.cおよびcnqueue.cのするNetlinkコネクタであります実装コード、およびcnproc.cは、サンプルアプリケーション、イベントコネクタと呼ばれるプロセスであり、私たちは、コネクタによって作成されたプロセスの監視を実現することができます。
システムアーキテクチャ:
(出典:https://www.slideshare.net/kerneltlv/kernel-proc-connector-and-containers)
特定のプロセス:
(出典:https://4hou.win/wordpress/?p=29586)
図NCPは、我々が開発する必要があるつまり、ユーザモードプログラムするNetlinkコネクタプロセス、です。
デモ
:それはプログラムを監視し、簡単なプロセスを開発し、イベント・コネクタのGithubのコースに基づいているhttps://github.com/ggrandes-clones/pmon/blob/master/src/pmon.c、次の三つの中核機能を:
nl_connect
:カーネルとの接続を確立するために、set_proc_ev_listen
:イベントのコースに登録handle_proc_ev
:イベントのコースを取り扱い
これは、図に示すように処理を行います。
私たちは、gcc pmon.c-o pmon
実行可能プログラムを生成する効果を確認し、プログラムを実行することができます。
PIDを取得した後、に行く/proc/<pid>/
あなたは、プロセスの下で得ることができます詳細についてディレクトリ。
使用条件
カーネルサポートするNetlinkコネクタ
- バージョン> 2.6.14
- カーネル構成の場合:
cat/boot/config-$(uname-r)|egrep'CONFIG_CONNECTOR|CONFIG_PROC_EVENTS'
長所と短所
利点
- 轻量级,在用户态即可获得内核提供的信息。
缺点
- 仅能获取到 pid ,详细信息需要查
/proc/<pid>/
,这就存在时间差,可能有数据丢失。
0x04 Audit
原理
Linux Audit 是 Linux 内核中用来进行审计的组件,可监控系统调用和文件访问,具体架构如下(图片来源:https://slack.engineering/syscall-auditing-at-scale-e6a3ca8ac1b8):
1.用户通过用户态的管理进程配置规则(例如图中的 go-audit ,也可替换为常用的 auditd ),并通过 Netlink 套接字通知给内核。
2.内核中的 kauditd 通过 Netlink 获取到规则并加载。
3.应用程序在调用系统调用和系统调用返回时都会经过 kauditd ,kauditd 会将这些事件记录下来并通过 Netlink 回传给用户态进程。
4.用户态进程解析事件日志并输出。
Demo
从上面的架构图可知,整个框架分为用户态和内核态两部分,内核空间的 kauditd 是不可变的,用户态的程序是可以定制的,目前最常用的用户态程序就是 auditd ,除此之外知名的 osquery 在底层也是通过与 Audit 交互来获取进程事件的(https://medium.com/palantir/auditing-with-osquery-part-one-introduction-to-the-linux-audit-framework-217967cec406)。下面我们就简单介绍一下如何通过 auditd 来监控进程创建。
首先安装并启动 auditd :
apt update && apt install auditd
systemctl start auditd && systemctl status auditd
auditd 软件包中含有一个命名行控制程序 auditctl
,我们可以通过它在命令行中与 auditd 进行交互,用如下命令创建一个对 execve
这个系统调用的监控:
auditctl -a exit,always -F arch=b64 -S execve
再通过 auditd 软件包中的 ausearch
来检索 auditd 产生的日志:
ausearch -sc execve | grep /usr/bin/id
整个过程的执行结果如下:
至于其他的使用方法可以通过 man auditd
和 man auditctl
来查看。
使用条件
内核开启 Audit
cat/boot/config-$(uname-r)|grep^CONFIG_AUDIT
优缺点
优点
- 组件完善,使用 auditd 软件包中的工具即可满足大部分需求,无需额外开发代码。
- 相比于 Netlink Connector ,获取的信息更为全面,不仅仅是 pid 。
缺点
- 性能消耗随着进程数量提升有所上升,需要通过添加白名单等配置来限制其资源占用。
0x05 Syscall hook
上面的 Netlink Connector 和 Audit 都是 Linux 本身提供的监控系统调用的方法,如果我们想拥有更大程度的可定制化,我们就需要通过安装内核模块的方式来对系统调用进行 hook 。
原理
目前常用的 hook 方法是通过修改 sys_call_table
( Linux 系统调用表)来实现,具体原理就是系统在执行系统调用时是通过系统调用号在 sys_call_table
中找到相应的函数进行调用,所以只要将 sys_call_table
中 execve
对应的地址改为我们安装的内核模块中的函数地址即可。
具体的实现细节可参考 YSRC 的这篇关于驭龙 HIDS 如何实现进程监控的文章:https://mp.weixin.qq.com/s/ntE5FNM8UaXQFC5l4iKUUw ,这里贴出文章里的一张图方便大家对整个流程有个直观地了解:
Demo
关于 Syscall hook 的 Demo ,我在 Github 上找了很多 Demo 代码,其中就包括驭龙 HIDS 的 hook 模块,但是这些都无法在我的机器上( Ubuntu 16.04 Kernel 4.4.0-151-generic )正常运行,这也就暴露了 Syscall hook 的兼容性问题。
最后我决定使用 Sysdig 来进行演示,Sysdig 是一个开源的系统监控工具,其核心原理是通过内核模块监控系统调用,并将系统调用抽象成事件,用户根据这些事件定制检测规则。作为一个相对成熟的产品,Sysdig 的兼容性做得比较好,所以这里用它来演示,同时也可以方便大家自己进行测试。
具体步骤如下:
1.通过官方的安装脚本进行安装:
curl-s https://s3.amazonaws.com/download.draios.com/stable/install-sysdig | sudo bash
2.检测内核模块是否已经安全:lsmod|grep sysdig
3.启动对 execve
的监控:sysdig evt.type=execve
最终的执行效果如下:
有关于 Sysdig 的更多信息可以访问其 wiki 进行获取,另外,Sysdig 团队推出了一个专门用于安全监控的工具 Falco ,Falco 在 Sysdig 的基础上抽象出了可读性更高的检测规则,并支持在容器内部署,同样,大家如果感兴趣可以访问其 wiki 获取更多信息。
使用条件
- 可以安装内核模块。
- 需针对不同 Linux 发行版和内核版本进行定制。
优缺点
优点
- 高定制化,从系统调用层面获取完整信息。
缺点
- 开发难度大。
- 兼容性差,需针对不同发行版和内核版本进行定制和测试。
0x06 总结
本文共讲了4种常见的监控进程创建的方法,这些方法本质上是对库函数或系统调用的监控,各有优劣,这里我再各用一句话总结一下:
- So preload :Hook 库函数,不与内核交互,轻量但易被绕过。
- Netlink Connector :从内核获取数据,监控系统调用,轻量,仅能直接获取 pid ,其他信息需要通过读取
/proc/<pid>/
来补全。 - Audit :从内核获取数据,监控系统调用,功能多,不只监控进程创建,获取的信息相对全面。
- Syscall hook :从内核获取数据,监控系统调用,最接近实际系统调用,定制度高,兼容性差。
对我个人来讲,单纯地看监控进程创建这方面,我还是更推荐使用 Netlink Connector 的方式,这种方式在保证从内核获取数据的前提下又足够轻量,方便进行定制化开发。如果是想要进行全方面的监控包括进程、网络和文件,Audit 是一个不错的选择。
另外本文是以 Demo 的形式对功能进行介绍,主要是想起到一个抛砖引玉的作用,至于各方法的稳定性并没有进行充分地测试,如果各位有这方面的测试数据欢迎在这里和大家分享讨论。
0x07 参考
https://4hou.win/wordpress/?p=29586
https://tech.meituan.com/2019/01/17/distributed-hids-cluster-architecture-design.html
https://www.ibm.com/developerworks/cn/linux/l-lo-use-space-audit-tool/index.html
https://linux-audit.com/configuring-and-auditing-linux-systems-with-audit-daemon/
https://my.oschina.net/macwe/blog/603583
https://mp.weixin.qq.com/s/ntE5FNM8UaXQFC5l4iKUUw
https://github.com/draios/sysdig
https://github.com/falcosecurity/falco