安全指南

此页面的目标是提供如何安全使用 APOC 的指南。不安全地使用 APOC 可能导致许多常见的软件漏洞,包括安全配置错误敏感数据泄露服务器端请求伪造语言注入

我们的指南建议对安全事项采取基于原则的方法,并分为三个部分。在第一部分中,我们将首先探讨我们的总体原则。在第二部分中,我们将讨论如何在执行查询之前为 APOC 创建一个安全的环境。最后,在第三部分中,我们将介绍如何在查询中安全地使用 APOC。

安全原则

本节介绍的安全原则为安全使用 APOC 提供了指导规则。如果遇到本页面未涵盖的任何安全挑战,建议用户遵循以下原则。

最小权限原则

也称为最小特权原则,最小权限原则规定工作负载应只被授予其操作所需的最小权限集。APOC 提供广泛的功能,任何 APOC 安装都不太可能完全使用所有功能。建议用户只启用那些严格需要的过程和函数。建议用户禁用所有其他过程和函数。

通过只启用所需的最低限度功能,用户将降低运行易受攻击过程所带来的风险,同时也能支持其功能需求。

深度防御原则

也称为冗余原则,深度防御原则规定用户应在软件堆栈的每个级别保护其安装,即使这样做可能看起来是多余的。

APOC 构建在由数据库和操作系统暴露和控制的接口之上。通过使用深度防御方法保护 APOC 安装,安装将被多层保护包裹,从而减轻任何层保护机制失败的风险。如果安装由 APOC、数据库和操作系统保护,则受保护的工作负载被单个 bug 利用的可能性就会降低。

安装

本节涵盖创建 APOC 安全环境的步骤。它涉及在编写查询之前保护 APOC。

保护 Neo4j

由于 APOC 提供的功能是基于数据库构建的,因此除非数据库本身是安全的,否则安装无法安全。因此,首要任务是确保数据库安装安全,这可以通过遵循现有数据库的安全清单来实现。本指南将更详细地重新讨论清单中涵盖的一些步骤。

保护 Neo4j 扩展

APOC 是一个 Neo4j 扩展,其功能比任何给定工作负载可能需要的都要多。与任何 Neo4j 扩展一样,有几种控制机制有助于确保只有所需的功能和过程安装到数据库中。

通过配置设置保护 Neo4j 扩展

数据库暴露了配置设置,可以在conf/neo4j.conf配置文件中进行配置。该配置文件控制哪些过程和函数可以加载到数据库中并解除限制。控制此行为的配置设置如下所示。

设置 描述 默认值

dbms.security.procedures.allowlist

要加载的函数和过程名称列表。

"*"

dbms.security.procedures.unrestricted

允许完全访问数据库的函数和过程名称列表。

""

建议遵循现有的安装指南,该指南规定了如何加载和解除限制工作负载所需的最小过程集。

通过 RBAC 保护 Neo4j 扩展

数据库暴露了一个基于角色的访问控制机制,用于精细调整允许哪些用户角色执行给定操作。这是 Neo4j Enterprise Edition 的功能,Community Edition 用户无法使用。

基于角色的访问控制还提供了限制导入和加载过程可以从哪些外部站点读取数据的能力。加载特权适用于所有可以提供 URL 的 APOC 过程。

有关于用户执行任何给定过程能力的执行过程特权。默认情况下,所有用户都有权以自己的权限级别执行任何过程。这意味着没有读取特权的用户无法通过过程读取数据,没有写入特权的用户无法通过过程写入数据。对于执行函数也存在类似的特权。

还有执行提升过程特权,涉及用户以完全权限执行任何给定过程的能力。这意味着原本不允许读取或写入数据库的用户,如果被授予提升过程特权,则被允许这样做。执行提升过程特权还覆盖了该过程上的任何加载特权,允许访问任何 URL。这些特权等同于执行管理过程特权。对于执行提升函数也存在类似的特权。

执行提升特权是一个强大的功能,有可能被滥用。有几个强大的 APOC 过程能够根据用户输入对数据库运行完整的查询。如果用户被授予以完全权限执行这些过程的提升特权,这相当于赋予用户运行任何 Cypher 查询的能力。

此类过程的示例包括

建议遵循默认行为,即只允许用户以自己的权限级别执行过程和函数,并避免在 APOC 中执行提升过程。当某个角色需要执行特定操作的特权时,通常可以通过授予其他特权来实现所需的限制,而无需依赖提升执行。

保护文件系统

APOC 包含多个可以读写文件系统中特定文件的过程。如果配置不当,这些过程可能导致高影响力的漏洞,例如敏感数据泄露。如果工作负载需要,用户需要启用过程来与文件系统交互,但仅限于特定目录。如果工作负载不需要,用户应完全限制过程与文件系统交互的能力。

可以从文件系统读取的过程示例包括apoc.import.*apoc.load.*。可以写入文件系统的过程示例包括apoc.export.*。允许数据库从文件系统读取的 Cypher 子句示例包括LOAD CSV

在操作系统层面保护文件系统

从操作系统的角度来看,只有一个进程在执行。APOC 不作为独立于数据库进程的操作系统进程存在。这意味着应用于数据库的所有操作系统限制也将应用于 APOC。因此,文件权限指南中为数据库规定的指导也适用于 APOC。

建议将数据库进程配置为只具有执行工作负载所需的最小文件系统权限集。这意味着限制数据库进程,使其仅在需要时才能与文件系统交互,即使如此也仅限于特定的目标目录,而不是整个文件系统。

在数据库层面保护文件系统

APOC 暴露了配置设置,用于控制是否允许与文件系统交互以及从哪个目录交互。这些设置可以在conf/apoc.conf文件中配置,如下所述。

设置 描述 默认值

apoc.export.file.enabled

启用将文件写入文件系统。

false

apoc.import.file.enabled

启用从文件系统读取文件。

false

apoc.import.file_use_neo4j_config

APOC 在读写文件系统时将遵循 Neo4j 的配置设置。

true

数据库还公开了配置设置,用于控制是否允许从文件系统读取文件以及从哪个目录读取。这些设置可以在conf/neo44j.conf文件中配置,如下所述。

设置 描述 默认值

dbms.security.allow_csv_import_from_file_urls

启用从文件系统读取文件。

false

server.directories.import

将文件读取限制到给定目录。

import

当 APOC 验证文件系统交互时,它会进行一系列检查。它首先检查是否允许读写。如果允许,它会检查可以执行操作的目录。

在确定是否允许读写时,APOC 首先验证其自身的配置设置是否已启用,然后检查数据库配置设置是否也已启用。只有当apoc.import.file_use_neo4j_config配置设置已启用时,APOC 才会检查数据库配置设置是否也已启用。

在确定允许读写文件的目录时,APOC 会检查apoc.import.file_use_neo4j_config配置设置是否已启用。如果启用,它将使用与数据库相同的目录限制。如果此配置设置未启用,则 APOC 可以在文件系统的任何位置读写。

安全指导

建议根据工作负载是否需要读取或写入文件而有所不同。有些工作负载不需要任何文件系统交互,有些只需要数据库能够读取文件,还有些则需要数据库和 APOC 都能够读取文件。

如果工作负载不需要任何文件系统的读写权限,则用户不应更改任何配置文件中的任何配置设置。默认情况下,Neo4j 和 APOC 查询均不允许读写文件。

如果工作负载只需要数据库能够读取文件,而不需要 APOC 也能这样做,则用户应仅通过设置dbms.security.allow_csv_import_from_file_urls=true来授予数据库此能力。用户无需对 APOC 配置设置进行任何修改,因为默认情况下它们不允许 APOC 读写文件到文件系统。

如果工作负载需要数据库和 APOC 都能够读写文件系统,那么用户仍应尽可能地保持限制。虽然这将需要在两个配置文件中都启用读写权限,但建议将 APOC 配置设置apoc.import.file_use_neo4j_config=true与 Neo4j 配置设置server.directories.import=import一起进行调整。

使用

上一节提供了在执行查询之前保护 APOC 安装的指南。本节将提供有关编写包含高风险 APOC 过程和函数的查询的建议。

通过 APOC 进行 Cypher 注入

Neo4j 知识库提供了关于防范 Cypher 注入的优秀入门指南,建议学习这些内容,以便更好地理解与 Cypher 注入相关的挑战。

许多 APOC 过程直接使用 Cypher,在底层,它们会根据接收到的输入构建并执行新的查询。这些过程对 APOC 用户来说是一个额外的挑战,他们需要能够识别它们,并理解它们能够提供的有限安全保证。

在下面的第一个示例中,初始查询调用apoc.refactor.rename.label过程,该过程反过来在幕后构建并执行第二个查询。第二个查询获取所有节点,移除一个标签,然后重新附加一个不同的标签。

CALL apoc.refactor.rename.label("Person", "Actor", [])
// executes MATCH (n:`Person`) REMOVE n:`Person` SET n:`Actor`

在下面的第二个示例中,初始查询调用apoc.cypher.run过程,该过程反过来在幕后构建并执行第二个查询。第二个查询获取所有节点并返回它们。

CALL apoc.cypher.run("MATCH (n) RETURN n", {})
// executes MATCH (n) RETURN n

上述示例中的两个过程都根据接收到的输入构建并执行新查询。这两个过程之间唯一的区别是它们接收的输入。在第一个示例中,过程知道输入表示Cypher 字面量。在第二个示例中,过程知道输入表示整个 Cypher 查询。第一个示例中的输入可以进行清理,而第二个示例中的输入无法清理。

APOC 保证会清理与 Cypher 字面量对应的输入。但是,APOC 无法为与整个 Cypher 查询对应的输入提供相同的保证。在后一种情况下,清理 Cypher 查询的责任委托给用户,建议用户仔细遵循上述 Cypher 注入指南。

加密函数

APOC 提供了一系列哈希函数,能够将任何对象转换为固定长度的统一字符串。此功能具有多种应用,包括加密和非加密。加密应用可能包括消息摘要和密码验证,而非加密用例可能包括均匀分发数据和数据去重。将 APOC 提供的、对需要加密安全性的用例而言不安全的哈希函数用于此类用例,可能导致高影响力的漏洞,例如弱加密

决定 APOC 提供的哈希函数是否具有加密安全性的关键因素是它是否具有不可逆性。如果给定输入易于计算哈希值,但给定哈希值难以计算原始输入,则认为哈希函数是不可逆的。

适用于加密应用程序的函数示例
安全指导

使用哈希函数时,首先分析工作负载是否需要不可逆哈希,然后确定给定 APOC 函数提供的哈希算法是否能够提供此特性,这一点非常重要。建议随时关注最新的安全研究,因为有时会在曾被认为是不可逆的哈希函数中发现弱点。

如果工作负载不需要不可逆哈希,那么 APOC 提供的加密不安全的哈希函数更可取,因为它们的执行速度更快。

© . All rights reserved.