【51CTO.com快译】使用Osquery应用程序方面的基本概念是对操作系统的许多方面(进程和用户等)执行的“表格抽象”。数据存储在表中,可以使用SQL语法、直接通过osqueryi外壳或通过osqueryd守护程序来查询。
本教程介绍如何安装该应用程序、如何运行基本查询以及如何在Linux系统管理工作中使用FIM(文件完整性监控)。
本教程将介绍:
- 如何安装Osquery
- 如何列出可用表
- 如何从osqueryi外壳执行查询
- 如何使用osqueryd守护程序监控文件完整性
软件需求和使用的约定
- 对SQL概念有基本知识
- 拥有执行管理任务的root权限
软件需求和Linux命令行约定
安装
我们基本上有两种方法来安装Osquery:第一种是从官方网站下载适合我们系统的软件包;第二种(通常是优选方法)是将Osquery存储库添加到发行版软件源。下面简要介绍这两种方法。
图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无法联系,因此看不到任何行。
结论
本教程介绍了使用Osquery应用程序方面的基本概念,该应用程序使用我们可以使用SQL语法查询的表格数据对操作系统的各个概念进行抽象。我们看到如何安装该应用程序、如何使用osqueryi外壳执行基本查询以及最后如何使用osqueryd守护程序设置文件监控。与往常一样,想更深入地了解该应用程序,建议查看项目文档:https://osquery.readthedocs.io/en/stable/。
原文标题:How to monitor file integrity on Linux using Osquery,作者:Egidio Docile
【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】