Encontrando vulnerabilidades no núcleo WordPress: A trilogia de um caçador de bugs, Parte III – Ultimato

Na Parte I, mostramos uma vulnerabilidade de elevação de privilégios, permitindo que qualquer assinante criasse e editasse mensagens da lixeira.

Na Parte II, discutimos como um invasor pode usar essa nova superfície para realizar SQL Injection no servidor atacado.

Para o terceiro e último ato, voltamos para encontrar uma falha na geração de página do WordPress, com a intenção de injetar códigos JS para qualquer objeto processado na página. O WordPress exibe vários objetos, incluindo diferentes cabeçalhos e templates, arquivos de mídia, calendário, atualizações de notícias, widgets de mídia social e muito mais.

No entanto, queremos que o nosso código malicioso se exiba em todos os momentos, não como elemento opcional. O WordPress permite o uso de tags HTML, bem como “códigos de acesso” – tags alternativas que proporcionem mais fácil incorporação de conteúdo dinâmico ao post.

A fim de fornecer essa funcionalidade com segurança, o WordPress filtra tags HTML usando uma variante do ‘KSES’, responsável por permitir um conjunto de tags enumeradas na white-list, em todo o conteúdo do post. Qualquer tag ou atributo não especificamente autorizado vai ser despojado a partir do conteúdo apresentado.

‘KSES’ faz um trabalho muito bom no qual proíbe todos os truques de evasão conhecidos. Precisamos ir mais fundo.

Shortcodes são tags HTML, projetados para habilitar conteúdo macro em mensagens. Novamente, o WordPress tem vários códigos de acesso internos para incorporar galerias, vídeos, áudio e assim por diante. Este conteúdo é inserido no conteúdo do post, substituindo a tag shortcode com tags HTML “regulares” que contêm a funcionalidade necessária.

O HTML resultante gerado por esses shortcodes é analisado e validado. Mais uma vez, o WordPress faz isso bem. Precisamos pensar fora da caixa.

Vamos torná-lo mais visual. Um link dentro de um post pode ter esta aparência:

wp1

 

 

Enquanto um shortcode pode ter esta aparência:

wp2

 

 

Ambos os tipos consistem de uma tag especifica seguida de atributos opcionais, que consistem em <NAME> = <VALUE> pares, onde <VALUE> é delimitado por apóstrofos (‘) ou aspas (“).

Lembra como o HTML e a validação de shortcode são realizados separadamente? Podemos explorar esse fato?

wp3

 

Quando ‘KSES’ validar essa string, ele se preocupará apenas com a correção HTML, que é a tag ‘<a>’. No nosso caso, temos uma tag válida com um atributo válido ‘href’ que contém um apóstrofo. Sem problemas para ‘KSES’.

wp4

 

Vamos olhar para o mesmo código do ponto de vista da validação do shortcode – o destacado ‘caption’ string é um valor atributo válido.

Observe o jogo que estamos jogando aqui, usando ambos os delimitadores (apóstrofe e aspas), iniciamos a tag ‘<a>’, e esprememos parte do atributo “href” para o atributo caption, até a primeira aspa.

Mas ele irá fundir?

Depois que toda a análise ocorre o HTML resultante final será parecido com este:

wp5

 

Sim! Nós fizemos com que o atributo ‘href’ permanecesse não fechado. O que precisamos agora é quaisquer aspas para fechar esse atributo e nós poderemos injetar um atributo HTML <a> arbitrário.

Isso é muito fácil, tudo o que precisamos é usar outra tag ‘<a>’ (bem fechada para validação KSES), contendo nossa injeção em um de seus atributos:

wp6

 

Gerando o código HTML a seguir:

wp7

 

E nós temos um XSS persistente.

Mais um obstáculo antes que possamos sentir orgulho na nossa habilidade de invadir – as mensagens que podemos controlar como assinante ainda estão no lixo, onde elas não estão sendo exibidas para qualquer um a menos que olhem para elas. Precisamos de alguma forma publicar nossos posts controlados de modo que os leitores vão processar o JavaScript injetado. Felizmente, os leitores vão mesmo ser usuários privilegiados.

O WordPress valida se temos permissão para publicar uma mensagem cada vez que o status do post está definido para “publicar” ou seus parente “futuro” e “privado”. Bem, não o tempo todo.

Dê uma olhada no método XMLRPC ‘mw_editPost ()’, disponível para qualquer usuário capaz de editar mensagens (nós podemos fazer isso usando o PE, é claro):

wp8

 

Esta função se preocupa em verificar se o usuário atual tem a capacidade de publicar posts, se o status requerido é “publicar”, negando o pedido, não foi possível publicá-lo. Mas a esperança não está perdida, altere o status para ‘private’.

Uma verificação esquecida é tudo que precisávamos para tornar a nossa XSS disponível a todos os usuários do site, incluindo administradores, é claro.

Mas espere, tem mais! Como um conveniente bônus, o mesmo vale para a criação de post “recorrente”, com efeito de promover o nosso post com XSS para sempre ser publicado no topo da primeira página para cada usuário do site.

POC
Mudando o Status do Post / Recorrente

wp9

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Conteúdo do Post com XSS

wp10

 

 

 

 

 

 

 

Epílogo

WordPress é a plataforma mais popular da web no mundo. Embora seja geralmente bem protegida, ainda poderíamos encontrar inúmeras falhas em seu núcleo, combinadas para causar implicações críticas sobre milhões de sites.

Acesse o conteúdo original (em inglês) no link.