如何使用Osquery在Linux上监控文件完整性?

本教程介绍如何安装该应用程序、如何运行基本查询以及如何在Linux系统管理工作中使用FIM(文件完整性监控)。

本教程将介绍:

  • 如何安装Osquery
  • 如何列出可用表
  • 如何从osqueryi外壳执行查询
  • 如何使用osqueryd守护程序监控文件完整性

软件需求和使用的约定

  • 对SQL概念有基本知识
  • 拥有执行管理任务的root权限

软件需求和Linux命令行约定

如何使用Osquery在Linux上监控文件完整性?

安装

我们基本上有两种方法来安装Osquery:第一种是从官方网站下载适合我们系统的软件包;第二种(通常是优选方法)是将Osquery存储库添加到发行版软件源。下面简要介绍这两种方法。

如何使用Osquery在Linux上监控文件完整性?

图1

通过软件包安装

可以从Osquery官方网站(https://osquery.io/downloads/official)下载签名的deb和rpm软件包,或下载更通用的打包文件。我们先选择要安装的版本,然后下载软件包。

建议选择最新的可用版本(截至发稿时4.1.2)。下载软件包后,我们可以使用发行版软件包管理器来安装。比如想在Fedora系统上安装该软件(假设软件包在当前的工作目录中),我们将运行:

$ sudo dnf install ./osquery-4.1.2-1.linux.x86_64.rpm 

使用存储库

我们还可以将rpm或deb存储库添加到发行版中。如果我们使用基于rpm的发行版,可以运行以下命令来完成任务:

$ curl -L https://pkg.osquery.io/rpm/GPG | sudo tee 


/etc/pki/rpm-gpg/RPM-GPG-KEY-osquery  


$ sudo yum-config-manager --add-repo https://pkg.osquery.io/rpm/osquery-s3-rpm.repo  


$ sudo yum-config-manager --enable osquery-s3-rpm-repo  


$ sudo yum install osquery  

借助上述Linux命令,我们可以将用来签名软件包的gpg公钥添加到系统中,然后添加存储库。最后,我们安装Osquery软件包。注意,在近期版本的Fedora和CentOS/RHEL中,yum只是dnf的符号链接,所以我们调用前者时,使用的却是后者。

如果你运行基于Debian的发行版,可以将deb存储库添加到软件源中,只要运行:

$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys  


1484120AC4E9F8A1A577AEEE97A80C63C9D8B80B  


$ sudo add-apt-repository 'deb [arch=amd64] https://pkg.osquery.io/deb deb main'  


$ sudo apt-get update  


$ sudo apt-get install osquery  

一旦软件包安装完毕,我们可以看一下软件的基本用法。

基本用法

Osquery让我们可以监控采用“表格抽象”的操作系统的不同方面,使用类似sqlite数据库上所用语法的SQL语法。针对表执行查询,表对操作系统的不同方面(比如进程和服务)进行抽象处理。

我们可以直接使用osqueryi交互式外壳来运行查询,也可以通过osqueryd守护程序来安排查询。下面这个例子显示了列出所有可用表的查询(还可以在此处https://osquery.io/schema/4.1.2#processes看到附有表描述的完整列表):

$ osqueryi  


osquery> .tables  


=> acpi_tables  


=> apt_sources  


=> arp_cache 


=> atom_packages  


=> augeas  


=> authorized_keys  


=> block_devices  


=> carbon_black_info  


=> carves  


=> chrome_extensions  


=> cpu_time  


=> cpuid  


=> crontab  


=> curl  


=> curl_certificate  


=> deb_packages  


=> device_file  


=> device_hash  


=> device_partitions  


=> disk_encryption  


=> dns_resolvers  


=> docker_container_labels  


=> docker_container_mounts  


=> docker_container_networks  


=> docker_container_ports  


=> docker_container_processes  


=> docker_container_stats  


=> docker_containers  


=> docker_image_labels  


=> docker_images  


=> docker_info  


=> docker_network_labels  


=> docker_networks  


=> docker_version  


=> docker_volume_labels  


=> docker_volumes  


=> ec2_instance_metadata  


=> ec2_instance_tags  


=> elf_dynamic  


=> elf_info  


=> elf_sections  


=> elf_segments  


=> elf_symbols  


=> etc_hosts  


=> etc_protocols  


=> etc_services  


=> file  


=> file_events  


=> firefox_addons  


=> groups  


=> hardware_events  


=> hash  


=> intel_me_info  


=> interface_addresses  


=> interface_details  


=> interface_ipv6  


=> iptables  


=> kernel_info  


=> kernel_integrity  


=> kernel_modules  


=> known_hosts  


=> last  


=> listening_ports  


=> lldp_neighbors  


=> load_average  


=> logged_in_users  


=> magic  


=> md_devices  


=> md_drives  

=> md_personalities 

=> memory_array_mapped_addresses  


=> memory_arrays  


=> memory_device_mapped_addresses  


=> memory_devices  


=> memory_error_info  


=> memory_info  


=> memory_map  


=> mounts  


=> msr  


=> npm_packages  


=> oem_strings  


=> opera_extensions  


=> os_version  


=> osquery_events  


=> osquery_extensions  


=> osquery_flags  


=> osquery_info  


=> osquery_packs  


=> osquery_registry  


=> osquery_schedule  


=> pci_devices  


=> platform_info  


=> portage_keywords  


=> portage_packages  


=> portage_use  


=> process_envs  


=> process_events  


=> process_file_events  


=> process_memory_map  


=> process_namespaces  


=> process_open_files  


=> process_open_sockets  


=> processes  


=> prometheus_metrics  


=> python_packages  


=> routes  


=> rpm_package_files  


=> rpm_packages  


=> selinux_events  


=> shadow  


=> shared_memory  


=> shell_history  


=> smart_drive_info  


=> smbios_tables  


=> socket_events  


=> ssh_configs  


=> sudoers  


=> suid_bin  


=> syslog_events  


=> system_controls  


=> system_info  


=> time  


=> ulimit_info  


=> uptime  


=> usb_devices  


=> user_events  


=> user_groups  


=> user_ssh_keys  


=> users  


=> yara  


=> yara_events  


=> yum_sources  

运行osqueryi命令,我们进入交互式外壳;我们可以从该外壳执行查询或指令。这是查询的另一个例子,这回列出所有运行中进程的pid和name。对process表执行查询(为便于阅读,查询的输出已截短):

osquery> SELECT pid, name FROM processes;  


+-------+------------------------------------+  


| pid | name |  


+-------+------------------------------------+  


| 1 | systemd |  


| 10 | rcu_sched |  


| 10333 | kworker/u16:5-events_unbound |  


| 10336 | kworker/2:0-events |  


| 11 | migration/0 |  


| 11002 | kworker/u16:1-kcryptd/253:0 |  


| 11165 | kworker/1:1-events |  


| 11200 | kworker/1:3-events |  


| 11227 | bash |  


| 11368 | osqueryi |  


| 11381 | kworker/0:0-events |  


| 11395 | Web Content |  


| 11437 | kworker/0:2-events |  


| 11461 | kworker/3:2-events_power_efficient |  


| 11508 | kworker/2:2 |  


| 11509 | kworker/0:1-events |  


| 11510 | kworker/u16:2-kcryptd/253:0 |  


| 11530 | bash |  


[...] |  


+-------+------------------------------------+  

甚至可以使用JOIN语句对连接表执行查询,就像我们在关系数据库中操作那样。在下面例子中,我们对processes表执行查询,通过uid列与users表进行连接:

osquery> SELECT processes.pid, processes.name, users.username FROM processes JOIN 


users ON processes.uid = users.uid;  


+-------+-------------------------------+------------------+  


| pid | name | username |  


+-------+-------------------------------+------------------+  


| 1 | systemd | root |  


| 10 | rcu_sched | root |  


| 11 | migration/0 | root |  


| 11227 | bash | egdoc |  


| 11368 | osqueryi | egdoc |  


| 13 | cpuhp/0 | root |  


| 14 | cpuhp/1 | root |  


| 143 | kintegrityd | root |  


| 144 | kblockd | root |  


| 145 | blkcg_punt_bio | root |  


| 146 | tpm_dev_wq | root |  


| 147 | ata_sff | root |  


[...]  


| 9130 | Web Content | egdoc |  


| 9298 | Web Content | egdoc |  


| 9463 | gvfsd-metadata | egdoc |  


| 9497 | gvfsd-network | egdoc |  


| 9518 | gvfsd-dnssd | egdoc |  


+-------+-------------------------------+------------------+  

文件完整性监控(FIM)

前面我们使用交互式外壳osqueryi来使用Osquery。想使用FIM(文件完整性监控),我们改用osqueryd守护程序。通过配置文件,我们列出了想要监控的文件。file_events 表中记录了涉及指定文件和目录的事件,比如属性变化。守护程序在指定的时间间隔后对该表运行查询,并在日志中通知何时发现新记录。不妨看看配置示例。

配置结构

Osquery的主配置文件是/etc/osquery/osquery.conf。该文件默认情况下不存在,于是我们要创建它。配置以JSON格式来提供。假设我们想要监控/etc下的所有文件和目录;下面显示了我们如何配置该应用程序:

{  


"options": {  


"disable_events": "false"  


},  


"schedule": {  


"file_events": {  


"query": "SELECT * FROM file_events;",  


"interval": 300  


}  


},  


"file_paths": {  


"etc": [  


"/etc/%%"  


],  


},  


}  

不妨分析上述配置。首先在options部分,我们将disable_events设为“false”,以便启用文件事件。

之后我们创建schedule部分:在该部分,我们可以描述和创建各种命名的调度查询。我们在本文中创建了一个查询,以便从file_events表选择所有列,这意味着每300秒(5分钟)执行一次。

安排查询后,我们创建了file_paths部分,在该部分指定要监控的文件。在该部分,每个键代表要监控一组文件的名称(Osquery术语中的类别)。这里“etc”键引用仅含有一个条目/etc/%%的列表。

%符号代表什么?指定文件路径时,我们可以使用标准通配符(*)或SQL通配符(%)。如果提供单通配符,它​将选择位于指定级别的所有文件和目录。如果提供双通配符,它​​将递归选择所有文件和文件夹。比如说,/etc/%表达式匹配/etc下面一级的所有文件和文件夹,而/etc/%%递归匹配/etc下的所有文件和文件夹。

如果需要,我们还可以使用配置文件中的exclude_paths部分,从提供的路径中排除特定文件。在该部分,我们只能引用file_paths部分中定义的类别(本例中是“etc”)。我们提供了要排除的文件列表:

"exclude_paths": {  


"etc": [  


"/etc/aliases"  


]  


}  

仅作为例子,我们从列表中排除了/etc/aliases文件。下面是最终配置的样子:

{  


"options": {  


"disable_events": "false"  


},  


"schedule": {  


"file_events": {  


"query": "SELECT * FROM file_events;",  


"interval": 20  


}  


},  


"file_paths": {  


"etc": [  


"/etc/%%"  


]  


},  


"exclude_paths": {  


"etc": [  


"/etc/aliases"  


]  


}  


}  

开启守护程序

配置已到位,我们可以开启osqueryd守护程序:

$ sudo systemctl start osqueryd 

为了使守护程序在系统启动时自动开启,我们要运行:

$ sudo systemctl enable osqueyd 

一旦守护程序运行,我们可以核实配置有效。仅举个例子,我们将修改/etc/fstab文件的许可权,将它们从644改为600:

$ sudo chmod 600 /etc/fstab 

现在我们可以核实文件更改以记录下来,只需阅读/var/log/osquery/osqueryd.results.log文件。下面是该文件的最后一行:

{  


"name":"file_events",  


"hostIdentifier":"fingolfin",  


"calendarTime":"Mon Dec 30 19:57:31 2019 UTC",  


"unixTime":1577735851,  


"epoch":0,  


"counter":0,  


"logNumericsAsNumbers":false,  


"columns": {  


"action":"ATTRIBUTES_MODIFIED",  


"atime":"1577735683",  


"category":"etc",  


"ctime":"1577735841",  


"gid":"0",  


"hashed":"0",  


"inode":"262147",  


"md5":"",  


"mode":"0600",  


"mtime":"1577371335",  


"sha1":"",  


"sha256":"",  


"size":"742",  


"target_path":"/etc/fstab",  


"time":"1577735841",  


"transaction_id":"0",  


"uid":"0"  


},  


"action":"added"  


}  

在上述日志中,我们可以清楚地看到在target_path "/etc/fstab"(第23行)上进行了ATTRIBUTES_MODIFIED操作(第10行),/etc/fstab是“etc”类别(第12行)的一部分。有必要注意这点:如果我们从osqueryi外壳查询file_events表,由于osqueryd守护程序和osqueryi无法联系,因此看不到任何行。

结论

相关推荐