
PoC: changedetection.io settings blind-merge mass assignment (CVE-2026-71204, Médio 6.3)
Produto: dgtlmoon/changedetection.io — v0.55.7
Arquivos: changedetectionio/blueprint/settings/__init__.py, changedetectionio/forms.py
CWE: CWE-284 — Controle de Acesso Impróprio
CVSS 3.1: AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:L — 6.3 (Médio)
CNA: Turan Security · Registro CVE
O handler de salvamento de /settings do changedetection.io constrói um dicionário de atualização a partir de form.data['application'] e o mescla às cegas nas configurações da aplicação armazenadas via .update(). Como checkboxes HTML só aparecem nos dados do formulário enviado quando estão marcados, um POST elaborado que simplesmente omite um campo de checkbox relevante para a segurança (como o que impõe a exigência de chave de API) é indistinguível, no nível do handler, de o usuário tê-lo desmarcado na interface — o .update() cego desliga silenciosamente essa configuração.
Uma requisição que nunca define explicitamente api_access_token_enabled (ou equivalente) como falso — apenas deixa o campo fora do corpo do POST — resulta na mesclagem das configurações da aplicação com essa proteção efetivamente desativada, sem nenhuma etapa explícita de confirmação ou sinal de auditoria que distinga "o usuário desmarcou isso" de "o campo não foi enviado".
/settings normalmente./settings com o campo api_access_token_enabled (ou qualquer outra configuração booleana protegida que esteja sendo testada) totalmente omitido do corpo, incluindo apenas campos não relacionados:
POST /settings HTTP/1.1
Content-Type: application/x-www-form-urlencoded
application-some_other_field=value
form.data['application'] → .update() no handler de salvamento das configurações trata o campo ausente da mesma forma que um "desligado" explícito, desativando silenciosamente a proteção sem que o usuário (ou um auditor revisando a requisição) veja um sinal explícito de desativação.Usar um .update() cego de dicionário a partir dos dados brutos do formulário confunde "campo ausente do POST" com "campo definido explicitamente como falso" para configurações baseadas em checkboxes — formulários HTML nunca enviam checkboxes desmarcados, portanto esse padrão é inseguro para qualquer campo de configuração com implicações de segurança.
Enumere explicitamente os campos de configuração booleanos esperados e defina os ausentes para o valor armazenado atual (não False), ou use uma biblioteca de formulários que distinga "não enviado" de "enviado como desmarcado" e valide explicitamente os interruptores relevantes para a segurança, em vez de por mesclagem cega de dicionário.