ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Bitcoin Core 钱包路径安全收紧:为什么含 `..` 与 `.` 的相对路径钱包名不再被允许

Bitcoin Core 钱包路径安全收紧:为什么含 `..` 与 `.` 的相对路径钱包名不再被允许 Bitcoin Core 钱包路径安全收紧为什么含..与.的相对路径钱包名不再被允许【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoinBitcoin Core 在近期版本中收紧了钱包命名规则包含..和.元素的相对路径钱包名以及名为/的钱包不再被允许。本文基于仓库中的发布说明 doc/release-notes-34544.md结合 钱包路径解析实现 与 多钱包功能测试完整讲清这一行为变更的规则边界、底层校验逻辑、触发该变更的安全动机以及依赖旧行为的用户的迁移方案。变更内容官方发布说明该变更记录在 doc/release-notes-34544.md 的 Wallet 小节中原文要点如下Wallets names that are relative paths including..and.elements, and wallets named/are no longer allowed. Any users that depended on this behavior can instead use absolute paths to their wallet or move their wallet to a safer path.翻译为具体规则相对路径中含..或.元素的钱包名被禁止例如bad/./path、bad/../path、../wallets/wallet以.或..开头的相对路径被禁止例如./、../、./wallet名为/文件系统根目录的钱包名被禁止。官方给出的迁移建议是两类对不在默认钱包目录内的钱包改用绝对路径引用或将钱包迁移到更安全的目录下。底层实现GetWalletPath的三层校验所有创建/加载钱包的路径入口最终都会经过 GetWalletPath 函数。它接收钱包名name按以下顺序执行三层校验util::Resultfs::path GetWalletPath(const std::string name) { const fs::path name_path fs::PathFromString(name); // name must be a normalized path, i.e. no . or .. except at the root if (name_path ! name_path.lexically_normal()) { return util::Error{Untranslated(Wallet name given as a path must be normalized)}; } // name cannot begin with ./ or ../ if (!name_path.empty() (*name_path.begin() fs::PathFromString(.) || *name_path.begin() fs::PathFromString(..))) { return util::Error{Untranslated(Wallet name given as a relative path cannot begin with ./ or ../, for wallets not in the walletdir, please use an absolute path.)}; } // Disallow path at root if (name_path.has_root_path() name_path.root_path() name_path) { return util::Error{Untranslated(Wallet name cannot be the root path)}; } // ... }三层校验各自的含义第一层路径必须已规范化normalizedlexically_normal()是 C17 文件系统库中对路径做字典序标准化的方法它会折叠.段、消解x/../y这类冗余。函数要求name_path与其规范化结果完全一致也就是说路径字符串本身不能携带任何.或..段文件系统根下的合法结构除外。这一层的设计意图值得注意它不是简单地把路径洗干净再使用而是拒绝未规范化的输入。因为规范化会隐藏调用方实际请求的路径与程序最终使用的路径之间的差异这种差异正是路径穿越path traversal类漏洞的温床。拒绝未规范化输入让请求的路径 解析的路径成为不变量。对应错误信息Wallet name given as a path must be normalized。第二层相对路径不能以./或../开头即使一个路径看起来是规范化的如果它从.或..段开始也会被单独拒绝。从源码结构看这一层是第一层的防御纵深../单独作为整个路径时其规范化结果仍是..无法再消解可能被第一层放行因此需要显式拦截。错误信息中也明确给出了替代方案提示Wallet name given as a relative path cannot begin with ./ or ../, for wallets not in the walletdir, please use an absolute path.即如果你的钱包不在默认钱包目录-walletdir中请改用绝对路径。第三层禁止根路径/name_path.has_root_path() name_path.root_path() name_path判断路径是否恰好就是文件系统根如/在 Windows 上还包括C:\。禁止以根目录作为钱包路径避免在文件系统根目录下创建或写入钱包数据。校验通过后的合法形态三层校验通过后GetWalletPath 继续检查解析出的绝对路径fsbridge::AbsPathJoin(GetWalletDir(), name_path)拼接 钱包目录必须满足以下四种形态之一否则返回Invalid -wallet path错误一个可以创建目录的位置一个已存在的目录一个指向目录的符号链接向后兼容-walletdir下一个已存在数据文件的文件名。也就是说普通相对路径仍然完全合法——mywallet、sub/dir/wallet这类不含./..段的名称都会相对 GetWalletDir() 解析。被禁止的只是含.、..段或以根路径形式出现的名字。变更覆盖的入口-wallet启动参数与 RPC这条命名规则并非只约束某一个入口而是所有按名字/路径解析钱包的公共入口因为 MakeWalletDatabase 在创建钱包数据库前统一调用GetWalletPathstd::unique_ptrWalletDatabase MakeWalletDatabase(const std::string name, const DatabaseOptions options, DatabaseStatus status, bilingual_str error_string) { const auto wallet_path GetWalletPath(name); if (!wallet_path) { error_string util::ErrorString(wallet_path); status DatabaseStatus::FAILED_BAD_PATH; return nullptr; } return MakeDatabase(*wallet_path, options, status, error_string); }因此以下使用方式都受同一规则约束启动参数-walletpath其定义为路径指向包含钱包数据与日志文件的目录若路径不是绝对路径则相对walletdir解释只能加载已存在的钱包不会创建新钱包见 src/wallet/init.cpp。这意味着启动时通过-wallet../outside/wallet之类的方式引用数据目录外部的钱包现在会直接失败RPCcreatewallet、loadwallet等按钱包名操作钱包的调用同样经过该校验链。测试证据功能测试中的非法钱包名清单test/functional/wallet_multiwallet.py 中的test_invalid_wallet_names用例完整覆盖了这条规则的三类非法输入与预期错误是验证该行为最直接的仓库内依据def test_invalid_wallet_names(self): self.log.info(Test weird paths are not allowed as wallet names) NON_NORMALIZED [bad/./path, bad/../path, /bad/./path, /bad/../path, ../, ./, ./wallet, ../wallets/../wallets/wallet] for name in NON_NORMALIZED: assert_raises_rpc_error(-4, Wallet name given as a path must be normalized, self.nodes[0].createwallet, name) INVALID_RELPATH [../wallets/wallet, .., .] for name in INVALID_RELPATH: assert_raises_rpc_error(-4, Wallet name given as a relative path cannot begin with ./ or ../, self.nodes[0].createwallet, name) INVALID_ROOT [/] if platform.system() Windows: INVALID_ROOT.extend([C:\\, C:]) for name in INVALID_ROOT: assert_raises_rpc_error(-4, Wallet name cannot be the root path, self.nodes[0].createwallet, name)从该测试可以读出三条规则边界输入类别示例触发错误含./..段的未规范化路径无论相对还是绝对bad/./path、/bad/../path、./walletWallet name given as a path must be normalized以./..开头的相对路径../wallets/wallet、..、.Wallet name given as a relative path cannot begin with ./ or ../文件系统根路径/Windows 下含C:\、C:Wallet name cannot be the root path注意一个细节./和../被归入未规范化一类第一层拦截而..、.单独作为完整路径时第一层的比较结果不变由第二层兜底拦截。这与上面 GetWalletPath 的两段判断顺序完全对应。为什么收紧路径解析的安全考量发布说明本身未展开动机但从源码结构可以推断其安全意图。相对路径与..段的组合会引入两类风险路径穿越../段允许钱包数据库LevelDB 数据、日志、备份文件被写入或读取到-walletdir之外。若不同来源配置文件、RPC 调用、启动参数拼装的相对路径在各自工作目录下解释..段的实际落点会变得难以审计。符号链接与规范化差异先接受任意路径再规范化会使用户请求的位置与程序实际使用的位置分叉。对以目录为单位存放数据库的钱包机制而言任何落点分叉都可能让备份、卸载unloadwallet会清理空目录见 src/wallet/wallet.cpp等后续操作作用到与预期不同的目录。拒绝未规范化输入 拒绝./、../前缀 拒绝根路径这三段组合把合法钱包名的空间收敛为钱包目录内无歧义的子路径或显式的绝对路径落点完全可预测。这也正是发布说明建议改用绝对路径的原因绝对路径天然不含相对解析歧义且不受当前工作目录影响。迁移建议依赖旧行为的用户怎么办发布说明给出的两条替代路径对应两类典型场景场景一把钱包放在数据目录之外如果你之前依赖-wallet../mywallet或类似写法把钱包数据放在-datadir之外的位置现在的正确做法是使用绝对路径启动参数bitcoind -wallet/absolute/path/to/walletdir参数说明见 src/wallet/init.cpp需要程序化加载时loadwallet /absolute/path/to/walletdir。绝对路径不含相对段能通过全部三层校验并且落点不受进程工作目录影响语义上与旧的相对写法等价但无歧义。场景二使用含.段的怪名字如果你之前以./wallet、bad/../path之类名字创建过钱包在旧版本中会被规范化后落在某个目录现在应当确认该名字实际解析到的真实目录即其规范化形态对应的目录将钱包数据目录移动到期望位置如-walletdir下的普通子目录用新名字/新路径加载。钱包数据库目录是 LevelDB 数据与日志的容器整体移动目录即可这正是发布说明中move their wallet to a safer path的含义。未受影响的用法普通钱包名如mainwallet、cold-storage、无.段的相对子路径如backups/cold以及指向现有目录或数据文件的绝对路径均不在此次变更影响范围内可继续使用。小结本次变更的核心是一条明确的命名规则钱包路径名必须已规范化、不得以./或../开头、不得是文件系统根路径其实现集中在 GetWalletPath经由 MakeWalletDatabase 统一约束-wallet启动参数与钱包相关 RPC并由 test/functional/wallet_multiwallet.py 的三类非法输入用例锁定行为。对使用者而言规则之外的一切照常工作规则之内的问题用法官方给出的标准解法只有两个——绝对路径或把钱包移到钱包目录下的安全位置。【免费下载链接】bitcoinBitcoin Core integration/staging tree项目地址: https://gitcode.com/GitHub_Trending/bi/bitcoin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表