如何使用 Osquery 监控 Linux 上的文件完整性
使用 osquery 应用程序涉及的基本概念是操作系统许多方面的“表格抽象”,例如进程、用户等。数据存储在可以使用 SQL 查询的表中。 语法,直接通过 osqueryi Shell 或通过 osqueryd 守护进程。
在本教程中,我们将了解如何安装应用程序、如何运行基本查询以及如何使用 FIM(文件完整性监控)作为 Linux 系统管理工作的一部分。
在本教程中您将学习:
如何安装osquery
如何列出可用的表
如何从 osqueryi shell 执行查询
如何使用 osqueryd 守护进程监控文件完整性
如何使用 Osquery 监控 Linux 上的文件完整性
SQL概念的基础知识
执行管理任务的 root 权限
安装
我们基本上有两个选择来安装 osquery:第一个是从官方网站下载适合我们系统的软件包;第二个是从官方网站下载适合我们系统的软件包。第二种,通常是首选,是将 osquery 存储库添加到我们的分发软件源中。在这里,我们将简要探讨这两种选择。
通过包安装
建议选择最新的可用版本(撰写本文时为 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 交互式 shell 直接运行查询,也可以通过 osqueryd 守护进程来调度它们。以下是列出所有可用表的查询示例(还可以找到带有表描述的完整列表 在线的):
$ 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 命令我们进入交互式 shell;我们可以从中发出查询和指示。这是另一个查询示例,这次列出所有正在运行的进程 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)
到目前为止,我们通过交互式 shell 使用 osquery
:osqueryi
。要使用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 行),属于“etc”ATTRIBUTES_MODIFIED
操作(第 10 行) 类别
(第 12 行)。值得注意的是,如果我们从 osqueryi Shell 查询 file_events 表,我们将看不到任何行,因为 osqueryd 守护进程和 osqueryi
不进行通信。
结论
在本教程中,我们了解了使用 osquery
应用程序所涉及的基本概念,该应用程序使用我们可以使用 SQL 语法查询的表格数据抽象了各种操作系统概念。我们了解了如何安装应用程序、如何使用 osqueryi shell 执行基本查询,以及最后如何使用 osqueryd 守护进程设置文件监控。我们只是触及了应用程序功能的表面;与往常一样,建议是查看项目文档以获取更深入的知识。