深入探索Trail of Bits的osquery扩展库:EFIgy集成与开发指南

本文详细介绍了Trail of Bits发布的osquery扩展库,重点解析了如何利用EFIgy API检查Mac设备EFI固件更新状态,并提供了完整的扩展开发指南和实际部署步骤。

宣布Trail of Bits osquery扩展存储库 - The Trail of Bits博客

Alessandro Gario
2017年12月14日
osquery

今天我们发布维护的osquery扩展存储库访问权限。我们的首个扩展利用Duo Labs EFIgy API来确定您的Mac设备群中的EFI固件是否为最新版本。

公开发布的osquery扩展示例非常稀少,相关文档也极为有限。本文旨在帮助未来开发者顺利完成为osquery编写扩展的过程。下文将详细描述我们如何为osquery实现EFIgy扩展。

关于EFIgy

在今年的Ekoparty会议上,Duo Labs展示了其对EFI固件支持状态和安全性的研究成果。这些软件组件对攻击者极具吸引力,因为它们运行在操作系统和虚拟机监控程序都无法触及的特权级别。Duo Labs收集并分析了过去三年所有公开发布的Apple更新,并通过检查来自不同组织的73,000多台Mac验证了这些信息。

研究人员发现,许多计算机运行着过时的固件,尽管所需的EFI更新本应捆绑在主机已正确安装的相同操作系统补丁中。Duo Labs据此创建了EFIgy服务,这是一个REST端点,可通过逻辑板ID和产品名称等详细信息访问任何已知Apple产品的最新OS和EFI版本。

编程方式查询EFIgy

EFIgy期望一个包含要查询系统详细信息的JSON对象。JSON请求不需要很多键;归结为硬件型号和软件版本:

1
2
3
4
5
6
7
8
9
{
  "board_id": "Mac-66E35819EE2D0D05",
  "smc_ver": "2.37f21",
  "build_num": "16G07",
  "rom_ver": "MBP132.0226.B20",
  "hw_ver": "MacBookPro12,1",
  "os_ver": "10.12.4",
  "hashed_uuid": ""
}

rom_ver键有些棘手。它不包含完整的EFI版本,因为(根据作者)它包含不一定有用或易于跟踪的时间戳。以点字符分隔,您只需要第一个、第三个和第四个字段。

顾名思义,hashed_uuid字段是SHA256摘要。要正确计算它,主网络接口的MAC地址必须前缀到系统UUID,如下所示:“0x001122334455” + “12345678-1234-1234-1234-1234567890AB”。

其余键不言自明,但请注意在虚拟机中运行时它们不会正确报告。board_id、hw_ver和rom_ver将报告虚拟机监控程序提供的虚拟组件信息。

查询服务很简单。JSON数据通过HTTP POST请求发送到以下REST端点:https://api.efigy.io/apple/oneshot。

服务器响应由三个JSON对象组成。将它们与您的原始值进行比较,以了解您的系统是否完全最新。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "latest_efi_version": {
    "msg": "<version>"
  },
  "latest_os_version": {
    "msg": "<version>"
  },
  "latest_build_number": {
    "msg": "<error message>",
    "error": "1"
  }
}

开发osquery扩展

Duo Labs提供的工具使用简单直接,但手动在设备群中的每个系统上运行它们并非易事。我们决定实现一个查询EFIgy的osquery扩展,这个想法来自Chris Long。

为什么编写扩展而不是虚拟表?我们决定将本机操作系统功能保留在核心中,并将所有其他内容转换为扩展。如果新功能使用外部服务或非本机组件,我们将默认编写扩展。

您唯一可用的工具集是标准库和手动导入项目的内容。osquery静态链接所有内容。您必须特别小心使用的库。不要依赖在运行时从程序加载动态库。

一旦环境准备就绪,表扩展不需要太多工作即可实现。您只需继承osquery::TablePlugin类并重写用于定义列和生成表行的两个方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class MyTable final : public osquery::TablePlugin {
 private:
  osquery::TableColumns columns() const override {
    return {
      std::make_tuple(
        "column_name",
        osquery::TEXT_TYPE,
        osquery::ColumnOptions::DEFAULT
      )
    }
  }

  osquery::QueryData generate(osquery::QueryContext& request) override {
    osquery::Row row;
    row["column_name"] = "value";

    return { row };
  }
};

然后必须将源文件放置在osquery/external内的专用文件夹中。请注意,您必须在文件夹名称前添加"extension_“前缀。否则,CMake项目将忽略它。

对于更复杂的项目,还可以添加CMakeLists.txt文件,使用以下辅助函数创建目标:

1
ADD_OSQUERY_EXTENSION(${PROJECT_NAME} source1.cpp source2.cpp)

您将可以访问osquery中的一些库,如Boost,但不能访问其他一些实用程序(例如非常有用的http_client类)。

开发扩展时没有推荐的步骤列表,但如果您计划编写多个扩展,我建议您将实用函数捆绑在可以轻松导入和重用的头文件中。保持所有外部库静态链接也是一个好主意,因为这将使重新分发更容易。

使用我们的osquery扩展存储库

由于没有地方提交我们的新功能,我们为扩展创建了一个新存储库。EFIgy扩展是第一个可用项目。预计会有更多跟进。

使用存储库很简单。但是,您必须首先克隆osquery的完整源代码,因为SDK不是可分发包的一部分。构建扩展很容易。您只需在osquery/external文件夹内创建要编译的源文件夹的符号链接,注意按照以下方案命名链接:extension_。然后您可以按照平台的常规构建过程,因为默认的ALL目标也会构建所有扩展。

1
2
3
4
5
6
7
8
9
cd /src/osquery-extensions
ln -s efigy /src/osquery/external/extension_efigy

cd /src/osquery
make sysprep
make deps

make -j `nproc`
make externals

扩展易于使用。您可以通过使用–extension参数指定它们的路径来测试它们(无论是使用shell还是守护进程)。由于它们是正常的可执行文件,您也可以在osquery之后启动它们。它们将通过Thrift自动连接并暴露新功能。官方文档很好地解释了这个过程。

要快速测试扩展,您可以从osqueryi shell启动它,或手动启动它并等待它连接到运行的osquery实例。

1
osqueryi --extension /path/to/extension

采取行动

如果您拥有Mac设备群,您现在可以使用osquery和EFIgy扩展监控它,并确保所有端点都已收到所需的软件和固件更新。

如果您在未来的某个时间阅读本文,您更有理由访问我们的osquery扩展存储库。我们将保持维护并随时间添加内容。

您有osquery扩展的想法吗?请在我们的Github存储库上提交问题。您需要osquery开发吗?请联系我们。

如果您喜欢这篇文章,请分享:
Twitter LinkedIn GitHub Mastodon Hacker News

页面内容
关于EFIgy
编程方式查询EFIgy
开发osquery扩展
使用我们的osquery扩展存储库
采取行动
近期文章
构建安全消息传递很难:对Bitchat安全辩论的细致看法
使用Deptective调查您的依赖项
系好安全带,Buttercup,AIxCC的评分回合正在进行中!
使您的智能合约超越私钥风险成熟
Go解析器中意外的安全陷阱
© 2025 Trail of Bits。
使用Hugo和Mainroad主题生成。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计