Cross-Site Scripting (XSS) Refletido

CibersegurançaBeginner
Pratique Agora

Introdução

O Cross-Site Scripting (XSS) Refletido é uma vulnerabilidade web comum que ocorre quando uma aplicação recebe dados em uma requisição HTTP e os inclui na resposta HTTP imediata de forma insegura. Como o script malicioso injetado é "refletido" pelo servidor web, ele é executado no navegador da vítima, permitindo que invasores roubem cookies de sessão, realizem ações em nome do usuário ou desfigurem o site.

O conceito fundamental é que o XSS é um bug de execução de código no lado do navegador. O servidor pode refletir o payload, mas é no navegador que o script realmente é executado e onde a fronteira de confiança é rompida.

Neste laboratório, você interagirá com uma aplicação web vulnerável hospedada localmente. Você aprenderá a abordagem sistemática para encontrar e explorar o XSS Refletido: localizar onde sua entrada é refletida, testar como a aplicação lida com caracteres especiais, escapar da estrutura HTML existente e, finalmente, executar um payload JavaScript malicioso.

Localizar Pontos de Reflexão

Nesta etapa, você aprenderá a identificar pontos de reflexão em uma aplicação web. Um ponto de reflexão é um local na resposta HTTP da aplicação onde a entrada fornecida na requisição HTTP é exibida (ou "refletida") de volta para você.

Iniciamos uma aplicação web vulnerável em sua máquina local, acessível na porta 8080. Esta aplicação possui um recurso de busca que utiliza um parâmetro de consulta chamado q.

Para encontrar um ponto de reflexão, você precisa enviar uma string única e facilmente identificável para a aplicação e verificar se ela aparece no código-fonte da resposta. Usaremos a ferramenta de linha de comando curl para enviar uma requisição HTTP GET para a aplicação.

A reflexão é necessária, mas não suficiente. Sua entrada deve retornar em um contexto onde a análise do navegador possa transformá-la em código executável.

Execute o seguinte comando em seu terminal para enviar uma string de teste REFLECTION_TEST para o endpoint de busca:

curl -s "http://localhost:8080/search?q=REFLECTION_TEST"

Observe atentamente a saída HTML impressa em seu terminal. Você verá sua entrada REFLECTION_TEST incorporada diretamente na estrutura HTML.

<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
    <h2>Search Results</h2>
    <form action="/search" method="GET">
        <input type="text" name="q" value="REFLECTION_TEST">
        <button type="submit">Search Again</button>
    </form>
</body>
</html>

Note que sua entrada é colocada dentro do atributo value de uma tag <input>. Isso confirma que a aplicação recebe nossa entrada da URL e a reflete diretamente na resposta HTML. Esta é a primeira condição necessária para uma vulnerabilidade de XSS Refletido.

Testar Filtragem de Caracteres (< > ")

Nesta etapa, você testará se a aplicação higieniza ou filtra caracteres HTML especiais.

A codificação sensível ao contexto é a verdadeira defesa aqui. Os caracteres perigosos diferem dependendo se a entrada cai no corpo de texto de um elemento, em um atributo HTML, em JavaScript ou em uma URL.

Encontrar um ponto de reflexão não é suficiente para confirmar uma vulnerabilidade XSS. Frameworks web modernos frequentemente codificam caracteres especiais automaticamente. Por exemplo, um sinal de menor que < pode ser convertido para &lt;. Se a aplicação codificar esses caracteres, o navegador os tratará como texto seguro em vez de código executável, impedindo o XSS.

Para injetar HTML ou JavaScript malicioso, normalmente precisamos de caracteres como o sinal de menor que < (para iniciar uma tag), o sinal de maior que > (para fechar uma tag) e aspas duplas " (para manipular atributos).

Vamos enviar um novo payload contendo esses caracteres especiais para ver como a aplicação lida com eles. Usaremos aspas simples ao redor da URL em nosso comando curl para evitar que o shell do Linux interprete os caracteres especiais.

Execute o seguinte comando para testar a filtragem de caracteres:

curl -s 'http://localhost:8080/search?q=FILTER_TEST<>"'

Examine a saída retornada pelo servidor:

<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
    <h2>Search Results</h2>
    <form action="/search" method="GET">
        <input type="text" name="q" value="FILTER_TEST<>"">
        <button type="submit">Search Again</button>
    </form>
</body>
</html>

Observe o atributo value na tag <input>. Os caracteres <>" são refletidos exatamente como os enviamos, sem qualquer codificação HTML (como &lt; ou &quot;). Essa falta de higienização confirma que a aplicação é altamente suscetível a Cross-Site Scripting.

Escapar de Contextos HTML

Nesta etapa, você aprenderá como escapar do contexto HTML atual para se preparar para a injeção de payload.

Este é o coração do trabalho prático com XSS: entender o contexto do analisador (parser) em que você começa e, em seguida, usar a sintaxe para escapar dele com segurança para um contexto mais perigoso.

O contexto é crucial no XSS. Em nossa aplicação vulnerável, o ponto de reflexão está dentro de um atributo HTML: value="[SUA_ENTRADA]". Se simplesmente injetarmos uma tag <script> imediatamente, ela se tornará parte do valor de texto do campo de entrada, em vez de ser executada pelo navegador.

Para forçar o navegador a executar nosso código, devemos primeiro "escapar" do atributo value e fechar a tag <input>.

Como o atributo está entre aspas duplas, podemos injetar uma aspa dupla " para fechar o atributo value prematuramente. Em seguida, podemos injetar um sinal de maior que > para fechar a própria tag <input>.

Vamos testar essa técnica de escape. Envie o seguinte payload para a aplicação:

curl -s 'http://localhost:8080/search?q=BREAKOUT">'

Revise a saída HTML cuidadosamente:

<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
    <h2>Search Results</h2>
    <form action="/search" method="GET">
        <input type="text" name="q" value="BREAKOUT">">
        <button type="submit">Search Again</button>
    </form>
</body>
</html>

Veja o que aconteceu com a tag <input>. O HTML agora lê value="BREAKOUT">">.

Nossa " injetada fechou com sucesso o atributo value, e nosso > injetado fechou a tag <input>. O "> restante no final é a aspa de fechamento original e o colchete do template da aplicação, que agora ficam pendentes como texto inofensivo na página.

Você escapou com sucesso do contexto do atributo HTML. O espaço imediatamente após o seu payload agora é tratado como conteúdo padrão do corpo HTML, onde novas tags podem ser introduzidas.

Executar Payload JavaScript

Nesta etapa final, você combinará a técnica de escape com um payload JavaScript malicioso para alcançar o Cross-Site Scripting.

Agora que você sabe como escapar da tag <input>, pode anexar qualquer HTML ou JavaScript válido imediatamente após sua sequência de escape. A prova de conceito mais comum para XSS é injetar uma tag <script> que dispara uma caixa de alert() do JavaScript.

Nosso payload completo será: "><script>alert("XSS")</script>

Veja como o payload funciona. A sequência "> escapa do atributo value e fecha a tag <input>. Em seguida, a tag <script> inicia um novo bloco de execução JavaScript. Dentro deste bloco, alert("XSS") é o código JavaScript que será executado. Finalmente, a tag </script> fecha o bloco de execução.

Execute o seguinte comando para injetar o payload XSS completo:

curl -s 'http://localhost:8080/search?q="><script>alert("XSS")</script>'

Examine a saída HTML final:

<!DOCTYPE html>
<html>
<head><title>Search Results</title></head>
<body>
    <h2>Search Results</h2>
    <form action="/search" method="GET">
        <input type="text" name="q" value=""><script>alert("XSS")</script>">
        <button type="submit">Search Again</button>
    </form>
</body>
</html>

Se uma vítima clicasse em um link contendo este payload em seu navegador (por exemplo, http://localhost:8080/search?q="><script>alert("XSS")</script>), o navegador analisaria o HTML de cima para baixo. Quando atingir a tag <script> injetada, ele executará o código JavaScript, exibindo uma caixa de alerta com a mensagem "XSS".

Em um ataque real, em vez de um alerta inofensivo, um invasor injetaria código para roubar os cookies de sessão da vítima (document.cookie) e enviá-los para um servidor malicioso, levando à tomada total da conta.

Resumo

Parabéns! Você concluiu com sucesso o laboratório de Cross-Site Scripting (XSS) Refletido.

Neste laboratório, você aprendeu a:

  • Identificar pontos de reflexão enviando strings únicas e analisando a resposta HTTP.
  • Testar a filtragem de caracteres para determinar se uma aplicação codifica com segurança caracteres HTML especiais.
  • Escapar de contextos de atributos HTML manipulando aspas e colchetes.
  • Construir e injetar um payload JavaScript completo para alcançar a execução de código dentro do navegador.

Compreender esses mecanismos é essencial tanto para identificar vulnerabilidades como pesquisador de segurança quanto para implementar a higienização de entrada e codificação de saída adequadas como desenvolvedor.