XSS - Guia Explicativo

20:45 Anderson Dadario 0 Comentarios



Muito ainda se ouve falar (e ainda vamos ouvir) a respeito de Cross-Site Scripting, embora poucos realmente saibam as diferenças entre os três tipos dessa antiga vulnerabilidade, como descobrí-la, como mitigá-la e qual o potencial de um ataque que utilize-se dela. É mais simples do que parece, confira os tópicos abaixo:
  1. O que é XSS?
  2. Quais são as implicações de um ataque baseado em XSS?
  3. Classificação XSS
    1. XSS Reflected
    2. XSS Stored
    3. XSS DOM Based
  4. Detecção
  5. Cenário didático
  6. Mitigação
  7. Teste seus conhecimentos

1.) O que é XSS?

É uma vulnerabilidade comumente encontrada em aplicações web, que permite a injeção de códigos no lado do cliente, ou seja, altera a página apenas no computador do usuário. Esta vulnerabilidade é subdividida em três categorias, sendo elas Refletido, Armazenado e baseado em DOM, explicadas abaixo.

2.) Quais são as implicações de um ataque baseado em XSS?

Depende. Varia desde um simples alerta na tela ao sequestro de sessão ou redirecionamento para sites maliciosos. Essa vulnerabilidade que era antigamente subestimada foi uma das responsáveis por grande parte dos ataques segundo a OWASP em seu top 10.

3.) Classificação de XSS

1.) XSS Reflected

Cross-Site Scripting Refletido acontece quando o servidor reflete o que enviamos sem filtrar o que o usuário colocou, ou seja, ao enviar um determinado parâmetro, o servidor repete-o no código-fonte da página sem tratar o que foi inserido, causando essa vulnerabilidade. Para entender melhor, confira o seguinte cenário:
  1. Acesso http://exemplo
  2. http://exemplo solicita Usuário e Senha
  3. Insiro um usuário não existente chamado "PablitoFonsecaDeOliveira"
  4. http://exemplo imprime na tela "O usuário 'PablitoFonsecaDeOliveira' não existe"
Até aí identificamos que o sistema está refletindo nosso input. Agora, para identificar o XSS Reflected:
  1. Acesso http://exemplo
  2. http://exemplo pede meu Usuário e Senha
  3. Insiro um usuário não existente chamado "<script>alert(1)</script>" - que na verdade é um conjunto de instruções HTML (por causa da tag <script>) e Javascript (por conta do alert(1)) que ao ser executado emite um alerta na tela.
  4. http://exemplo imprime na tela "O usuário '' não existe" e gera uma caixa de alerta com o conteúdo "1"
Ilustração de cenários com usuários bem e mal intencionados:

Para relembrar, as premissas para execução do XSS Reflected são:
  1. Refletir o input do usuário
  2. Não filtrar os caracteres nocivos - no caso "<" e ">"

2.) XSS Stored

Armazenado, como o próprio nome já diz, é quando o código malicioso a ser injetado não foi filtrado e está armazenado, persistido em algum componente da aplicação, que comumente refere-se ao banco de dados. Quando alguma página for imprimir na tela o conteúdo armazenado, caso não filtre os caracteres nocivos, o XSS Stored é disparado. Acompanhe os cenários abaixo para um melhor entendimento:
  1. Acesso http://exemplo/cadastro
  2. http://exemplo/cadastro solicita meu Nome e Senha para me cadastrar
  3. Preencho "Anderson Dadario" no nome e "teste" na senha
  4. Após o cadastro sou redirecionado para uma tela que imprime "Seja bem vindo Anderson Dadario"

Esse é o cenário feliz, porém se eu for um usuário que deseje verificar a existência da vulnerabilidade XSS Stored, o cenário seria:

  1. Acesso http://exemplo/cadastro
  2. http://exemplo/cadastro solicita meu Nome e Senha para me cadastrar
  3. Preencho "<script>alert(1)</script>" no nome e "teste" na senha
  4. Após o cadastro sou redirecionado para uma tela que imprime "Seja bem vindo" e gera uma caixa de alerta com o conteúdo "1"
Ilustração:
Para relembrar, as premissas para execução do XSS Stored são:
  1. Não filtrar os caracteres nocivos - no caso "<" e ">" ao persistir o input do usuário
  2. Não filtrar os caracteres nocivos - no caso "<" e ">" ao imprimir o dado persistido

3.) XSS DOM Based

Este é o tipo mais difícil de ser encontrado entre os três porque depende de uma vulnerabilidades em algum dos componentes da página (geralmente códigos javascript) caracterizado por ser disparado no momento de execução ao invés de vir embutido no código fonte. Complicou? Vou explicar com o exemplo recentemente encontrado no AddThis, site que fornece serviço de compartilhamento para conteúdo.
  1. A página http://exemplo utiliza o componente do AddThis para compartilhar suas notícias, gerando esse resultado:
  2. Acesso http://exemplo/#"></fb:like><img/src="aaa"/onerror="alert('DomXss Found!')
  3. É gerado um alerta na tela escrito "DomXss Found!"
Atenção: repare que o código injetado foi inserido após o caractere sustenido (#), extremamente comum neste tipo de XSS. Conhece a utilidade do sustenido? Em caso negativo, leia a seção abaixo:

A história do sustenido e introdução ao Ajax ...

O sustenido era utilizado antigamente para criar links âncoras para a mesma a página, como víamos nos sites de letras de músicas onde você escolhia o artista por letra "A B C D E" e ao clicarmos eramos redirecionados para a mesma página, porém apenas para uma seção diferente, ou seja, só a barra de rolagem se movimentava.
Atualmente, o sustenido é utilizado por bibliotecas Javascript para manter um histórico de requisições Ajax, requisições essas que atualizam apenas o "miolo" da página, ao invés de carregar a página inteira por completo. Para se ter uma idéia, quando você acessa o Facebook na página "Pessoas que você talvez conheça", desce a barra de rolagem até o final e repara que uma imagem de "carregando" é executada e mais sugestões aparecem, você está presenciando uma chamada Ajax! Note também que a URL de sua barra de endereços não é alterada.
E  se o Facebook quisesse paginar essas sugestões que aparecem na sua tela? Ou seja, criar uma URL Única que, ao ser acessada, levasse para a página atual com essa mesma quantidade de sugestões de amigos? Seria necessário adicionar algum mecanismo para toda vez que o script Ajax que retorna mais sugestões for executado, fosse atualizada a URL.
Daí que entra o sustenido, interpretado por uma rotina em javascript que consegue ler o que vem depois do sustenido e gerar novamente a sugestão de amigos até a quantidade desejada. E justamente nessa interpretação é possível descobrir uma vulnerabilidade de Cross-Site Scripting baseado em DOM. E afinal, que raios é DOM ?

... voltando ao DOM based XSS

Document Object Model (DOM), segundo a Wikipedia, é uma especificação da W3C, independente de plataforma e linguagem, onde pode-se dinamicamente alterar e editar a estrutura, conteúdo e estilo de um documento eletrônico, permitindo que o documento seja mais tarde processado e os resultados desse processamento, incorporados de volta no próprio documento.
E, justamente, nesse processo de alteração da uma estrutura da página, que se dá por Javascript nesse contexto, caso o código estiver vulnerável, a vulnerabilidade  de Cross-Site Scripting baseada em DOM será disparada - isso tudo sem alterar o código fonte.
No código vulnerável, note que ao chegar na linha que contém o ".innerHTML", método que substitui o valor contido entre determinada tag HTML, a vulnerabilidade é disparada:

if (F.href === _1) {d = _8.util.clone(E.share.url_transforms || {});d.defrag = 1;F.href = _8.track.mgu(E.share.url, d);//-- Location}for (A in F) {
B += " " + A + "=\"" + F[A] + "\"";//-- Attribute Set
}
if (!E.share.xid) {
E.share.xid = _8.util.cuid();
}
f[F.href] = {};
for (A in E.share) {
f[F.href][A] = E.share[A];&nbsp;
}
G.innerHTML = "<fb:like br="br"
ref="\">_8.share.gcp(E.share, E.conf,".like").replace(",", "_")
+ "\" " + B + "</fb:like>"; //-- DomXss
p(G);

4.) Detecção

Você pode encontrar vulnerabilidades de Cross-Site Scripting manualmente conforme as provas de conceito acima, mas isso pode ser árduo se a aplicação for grande ou seu tempo for curto, exceto se estiver buscando por DOM based, visto que é um dos tipos mais difíceis de encontrar. 

5.) Cenário Didático
Feita a detecção, uma série de possibilidades para o usuário mal intencionado surgem, confira um dos possíveis cenários:

6.) Mitigação

Para começar, audite o controle de validação de dados de entrada (tudo que o usuário envia) e validação de dados de saída (tudo que o servidor envia), certificando-se que nada além do esperado é processado.
  • Crie uma whitelist de caracteres permitidos, assim você evita não apenas vulnerabilidades de XSS como outras vulnerabilidades de injeção de código.
  • Utilize uma codificação de confiança, como o UTF-8. E sim, encodings estão relacionados com XSS.
  • Utilize um Web Application Firewall (WAF), mas não dependa apenas dele!
  • Envie na resposta do servidor o header X-XSS-Protection: 1; mode=block, assim o navegador do usuário tentará bloquear XSS caso detecte.
  • Utilize as flag HttpOnly nos cookies para não serem manipulados por Javascript e também a flag Secure para forçar o tráfego apenas por HTTPS.
  • Confira outras recomendações na página da OWASP.

7.) Teste Seus Conhecimentos

Isso mesmo, coloque em prática o que aprendeu aqui em um mini-game do Google: https://xss-game.appspot.com/
Bons estudos!

0 comentários: