产品: dgtlmoon/changedetection.io — v0.55.7
文件: changedetectionio/blueprint/settings/__init__.py、changedetectionio/forms.py
CWE: CWE-284 — 访问控制不当
CVSS 3.1: AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:L — 6.3(中危)
CNA: Turan Security · CVE 记录
changedetection.io 的 /settings 保存处理器从 form.data['application'] 构建更新字典,并通过 .update() 将其盲目合并到已存储的应用设置中。由于 HTML 复选框只有在被勾选时才会出现在提交的表单数据中,因此与用户在界面中取消勾选相比,经过精心构造、只是省略了与安全相关的复选框字段(例如强制要求 API 密钥的那个)的 POST,在处理器层面无法区分——这种盲目 .update() 会静默地将该设置关闭。
一个从未显式将 api_access_token_enabled(或等效字段)设为 false 的请求——只是将该字段从 POST 主体中省略——会导致应用设置被合并后该保护实际上被禁用,且没有任何明确的确认步骤或审计信号来区分“用户取消勾选”与“字段未发送”。
/settings 页面。/settings 提交一个 POST,在主体中完全省略 api_access_token_enabled 字段(或任何正在测试的受保护布尔设置),只包含无关字段:
POST /settings HTTP/1.1
Content-Type: application/x-www-form-urlencoded
application-some_other_field=value
form.data['application'] → .update() 合并操作会将缺失字段与显式“关闭”同等对待,从而在用户(或审查请求的审计人员)看不到任何显式关闭信号的情况下静默禁用该保护。使用来自原始表单数据的盲目字典 .update(),会将“POST 中缺少字段”与“字段被显式设为 false”混为一谈——HTML 表单永远不会提交未勾选的复选框,因此对于任何具有安全影响的设置字段,这种模式都是不安全的。
显式枚举预期的布尔设置字段,并将缺失的字段默认为其当前存储值(而非 False),或者使用能够区分“未提交”与“作为未勾选提交”的表单库,并显式验证与安全相关的开关,而不是通过盲目字典合并。