OpenRefine Zip Slip 漏洞:简介
OpenRefine是一个基于Java的开源数据清理和转换工具。这包括加载不同类型的数据、清理、转换和扩展。所有这些都可以通过浏览器访问 OpenRefine 的 Web 界面来完成。它拥有近 10k 颗星和约 1800 个分支,是GitHub 上最受欢迎的项目之一。
在我们不断努力帮助保护开源项目并改进我们的清洁代码解决方案的过程中,我们定期通过 SonarCloud 扫描开源项目并评估结果。事实上,每个人都可以做到——SonarCloud是一款针对开源项目的免费代码分析产品,无论其规模或语言如何。
SonarCloud 报告的调查结果之一是 OpenRefine 中的 Zip Slip 漏洞,这让我们感到好奇。Zip Slip 漏洞是由于提取档案时路径验证不充分而导致的,这可能允许攻击者覆盖现有文件或将文件提取到非预期位置。
在本文中,我们概述了此漏洞的影响,并解释了如何使用 SonarCloud 检测此漏洞和其他代码漏洞。此外,我们还解释了攻击者如何利用该漏洞,并描述了开发人员在尝试修复该漏洞时可能陷入的典型陷阱。
OpenRefine Zip Slip 漏洞:影响
OpenRefine 3.7.3 及以下版本在项目导入功能中容易出现Zip Slip 漏洞( CVE-2023-37476)。尽管 OpenRefine 设计为仅在用户计算机上本地运行,但攻击者可以诱骗用户导入恶意项目文件。一旦导入该文件,攻击者就可以在用户的计算机上执行任意代码:
OpenRefine Zip Slip 漏洞:技术细节
在节中,我们将深入探讨该漏洞的技术细节。
漏洞发现
SonarCloud 是我们基于云的代码分析服务。它使用最先进的静态代码分析技术来查找代码中的质量问题、错误和安全漏洞。通过最近添加的更深入的 SAST技术,甚至可以发现因使用第三方依赖项而引入的隐藏安全漏洞。
通过突出显示的代码流可以清楚地看到,该untar方法迭代存档中的所有文件,并使用该tarEntry.getName()方法创建一个新File对象,然后将其传递到FileOutputStream以提取该文件。这引入了 Zip Slip 漏洞,允许攻击者destDir通过使用名为 .zip 的文件创建存档,在预期文件夹 ( )之外写入文件../../../../tmp/pwned。
存在漏洞的untar方法是从该FileProjectManager.importProject方法调用的,该方法处理现有Refine项目文件的导入:
OpenRefine/main/src/com/google/refine/io/FileProjectManager.java
public
class
FileProjectManager
extends
ProjectManager
{
// ...
public
void
importProject
(...)
{
// ..
untar(destDir, inputStream);
可以通过直接上传存档或提供存档的 URL 来导入项目。该功能在 Web 界面上如下所示:
相应的端点称为/command/core/import-project。尽管 OpenRefine 的此端点和所有其他端点不需要身份验证,但 OpenRefine 应该在用户计算机上本地运行。此外,所采用的 CSRF 保护可防止在另一个网站的上下文中执行的恶意 JavaScript 代码执行未经授权的操作。为了利用该漏洞,攻击者仍然可以诱骗用户导入恶意项目。
通过自动重新加载进行利用
该漏洞为攻击者提供了强大的原语:将具有任意内容的文件写入文件系统上的任意位置。对于以root特权运行的应用程序,有多种可能性可以将其转换为操作系统上的任意代码执行:向文件添加新用户passwd、添加 SSH 密钥、创建 cron 作业等等。对于以低权限用户的权限运行的应用程序,机会更加有限,但仍然会发生 - 今年早些时候,我们记录了一种通过编写特定于站点的配置挂钩来实现代码执行的独特方法,该方法仅限于 Python 应用程序。
除了这些通用技术之外,应用程序本身可能还存在一些可供攻击者利用的功能。对于 OpenRefine,该应用程序实现了自动重新加载功能,该功能会定期扫描文件夹WEB-INF以查找更改,并WebAppContext在文件更改时重新启动:
OpenRefine/server/src/com/google/refine/Refine.java
class
RefineServer
extends
Server
{
static
private
void
scanForUpdates
(...)
{
// ...
scanList.add(
new
File(contextRoot,
"WEB-INF/web.xml"
));
findFiles(
".class"
,
new
File(contextRoot,
"WEB-INF/classes"
), scanList);
findFiles(
".jar"
,
new
File(contextRoot,
"WEB-INF/lib"
), scanList);
// ...
scanner.addListener(
new
Scanner.BulkListener() {
public
void
filesChanged
()
{
try
{
context.stop();
context.start();
WEB-INF/classes该文件夹中的所有类都会在WebAppContext. 这意味着攻击者可以覆盖.class此文件夹中的现有文件,从而触发重新加载并随后执行攻击者的.class文件,从而能够执行任意代码。
缓解措施、陷阱和补丁
为了缓解此漏洞,需要确保所有文件都提取到预期的基本文件夹下。您可能想到的一种方法是使用该getCanonicalPath方法以字符串形式检索绝对且唯一的路径,然后利用该startsWith方法验证目标路径是否是预期基本文件夹的一部分:
注意:这并不能完全修复漏洞!你能发现这里的问题吗?
while
((tarEntry = tin.getNextTarEntry()) !=
null
) {
File destEntry =
new
File(destDir, tarEntry.getName());
+
if
(!destEntry.getCanonicalPath().startsWith(destDir.getCanonicalPath())) {
+
throw
new
IllegalArgumentException(
"Zip archives with files escaping their root directory are not allowed."
);
+ }
该getCanonicalPath方法删除了终止路径分隔符,这使得它仍然容易受到部分路径遍历的影响!
假设基文件夹 ( destDir) 被定义为用户 john ( "/home/john/") 的主目录,则删除尾部斜杠,结果是"/home/john". 这意味着攻击者仍然可以部分路径遍历到以相同字符开头的另一个用户的主目录,例如,"/home/johnny/"因为这通过了检查:
"/home/johnny/.ssh/id_rsa"
.
startsWith
(
"/home/john"
) ==
true
https://github.com/aws/aws-sdk-java/security/advisories/GHSA-c28r-hw5m-5gv3可以在此处找到此类部分路径遍历漏洞的现实示例, Jonathan Leitschuh 的相关
https:
//www.youtube.com/watch?v=zTtbVxGEq8A
Black Hat 演讲对此进行了更详细的介绍。
原文始发于微信公众号(Ots安全):OpenRefine Zip Slip 任意代码执行-CVE-2023-37476
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论