⌘+k ctrl+k
1.3 (稳定版)
搜索快捷键 cmd + k | ctrl + k
保护 DuckDB

DuckDB 功能非常强大,这可能会带来问题,尤其是在运行不受信任的 SQL 查询时,例如来自面向公众的用户输入。本页面列出了一些选项,以限制恶意 SQL 查询可能造成的损害。

保护 DuckDB 的方法因您的用例、环境和潜在攻击模型而异。因此,请仔细考虑与安全相关的配置选项,尤其是在处理机密数据集时。

如果您计划在应用程序中嵌入 DuckDB,请参阅“嵌入 DuckDB” 页面。

报告漏洞

如果您发现潜在漏洞,请通过 GitHub 机密报告

安全模式 (CLI)

DuckDB 的 CLI 客户端支持“安全模式”,此模式可阻止 DuckDB 访问数据库文件之外的外部文件。可以通过命令行参数或点命令激活此模式

duckdb -safe ...
.safe_mode

限制文件访问

DuckDB 可以通过其 CSV 解析器的read_csv 函数或通过read_text 函数读取目录并任意文件。这使得从本地文件系统读取成为可能,例如

SELECT *
FROM read_csv('/etc/passwd', sep = ':');

禁用文件访问

文件访问可以通过两种方式禁用。首先,您可以禁用单个文件系统。例如

SET disabled_filesystems = 'LocalFileSystem';

其次,您还可以通过将enable_external_access 选项设置为 false 来完全禁用外部访问。

SET enable_external_access = false;

此设置意味着

  • ATTACH 无法附加到文件中的数据库。
  • COPY 无法从文件读取或写入文件。
  • 诸如 read_csvread_parquetread_json 等函数无法从外部源读取。

allowed_directoriesallowed_paths 选项

您可以使用 allowed_directoriesallowed_paths 选项(分别为)限制 DuckDB 对特定目录或文件的访问。这些选项允许对文件系统进行细粒度访问控制。例如,您可以将 DuckDB 设置为仅使用 /tmp 目录。

SET allowed_directories = ['/tmp'];  
SET enable_external_access = false;  
FROM read_csv('test.csv');  

应用此设置后,DuckDB 将拒绝读取当前工作目录中的文件

Permission Error:
Cannot access file "test.csv" - file system operations are disabled by configuration  

机密信息

机密信息用于管理登录 AWS 或 Azure 等第三方服务的凭据。DuckDB 可以使用 duckdb_secrets() 表函数显示机密信息列表。默认情况下,这会清除任何敏感信息,例如安全密钥。可以将 allow_unredacted_secrets 选项设置为显示安全密钥中包含的所有信息。如果您正在运行不受信任的 SQL 输入,建议不要打开此选项。

查询可以访问在机密信息管理器中定义的机密信息。例如,如果定义了用于与拥有给定 AWS S3 存储桶写入权限的用户进行身份验证的机密信息,则查询可能会写入该存储桶。这适用于持久性机密信息和临时机密信息。

持久性机密信息以未加密的二进制格式存储在磁盘上。它们具有与 SSH 密钥相同的权限,即 600,这意味着只有运行 DuckDB(父)进程的用户才能读取和写入它们。

锁定配置

出于安全原因,与安全相关的配置设置通常会自动锁定。例如,虽然我们可以使用 SET allow_community_extensions = false 禁用社区扩展,但事后若不重启数据库,则无法再次启用它们。尝试这样做将导致错误

Invalid Input Error: Cannot upgrade allow_community_extensions setting while database is running

这可以防止不受信任的 SQL 输入重新启用出于安全原因而明确禁用的设置。

然而,许多配置设置不会自动禁用,例如资源约束。如果您允许用户在自己的硬件上不受限制地运行 SQL 语句,建议您在完成自己的配置后使用以下命令锁定配置

SET lock_configuration = true;

这可以防止从那时起修改任何配置设置。

预处理语句以防止 SQL 注入

与其他 SQL 数据库类似,建议使用 DuckDB 中的预处理语句,以防止SQL 注入

因此,避免为查询连接字符串

import duckdb
duckdb.execute("SELECT * FROM (VALUES (32, 'a'), (42, 'b')) t(x) WHERE x = " + str(42)).fetchall()

相反,请使用预处理语句

import duckdb
duckdb.execute("SELECT * FROM (VALUES (32, 'a'), (42, 'b')) t(x) WHERE x = ?", [42]).fetchall()

限制资源使用

DuckDB 会占用大量 CPU、RAM 和磁盘空间。为避免拒绝服务攻击,可以限制这些资源。

例如,可以使用以下方式设置 DuckDB 可以使用的 CPU 线程数

SET threads = 4;

其中 4 是允许的线程数。

例如,最大内存 (RAM) 量也可以限制为

SET memory_limit = '4GB';

临时文件目录的大小可以用以下方式限制

SET max_temp_directory_size = '4GB';

扩展

DuckDB 具有强大的扩展机制,其权限与运行 DuckDB(父)进程的用户相同。这带来了安全方面的考虑。因此,我们建议查看保护扩展的配置选项。

权限

避免以 root 用户身份运行 DuckDB(例如,使用 sudo)。没有充分的理由以 root 身份运行 DuckDB。

通用解决方案

保护 DuckDB 还可以通过已证实的方法来支持,例如

  • 通过 chroot 限制用户权限,依赖于操作系统
  • 容器化,例如 Docker 和 Podman
  • 在 WebAssembly 中运行 DuckDB

本节页面