Cross-site scripting como previnir ?
Cross-Site Scripting (XSS)
Também conhecido como XSS, é uma vulnerabilidade de segurança que permite que um atacante injete scripts maliciosos em páginas web visualizadas por outros usuários. Esses scripts geralmente são escritos em JavaScript e podem ser usados para roubar informações, manipular a interface do usuário ou realizar ações em nome do usuário sem o seu consentimento.
Como Funciona?
- Entrada Maliciosa: O atacante insere código malicioso em um campo de entrada ou URL de uma aplicação vulnerável.
- Execução no Navegador: O código malicioso é enviado ao navegador de outros usuários como parte da página web.
- Impacto:
- Roubo de cookies, tokens de sessão ou dados sensíveis.
- Redirecionamento para sites maliciosos.
- Modificação da interface ou conteúdo da página.
Tipos de XSS
- Refletido: O script malicioso é enviado na requisição e refletido diretamente na resposta sem validação.
- Armazenado: O script é armazenado no servidor (em um banco de dados, por exemplo) e executado sempre que a página é carregada.
- Baseado em DOM: O script é executado diretamente no lado do cliente, manipulando o Document Object Model (DOM).
Prevenção
- Sanitização e Validação: Limitar e limpar entradas do usuário.
- Escapar Saída: Converter caracteres especiais em entidades HTML.
- Usar APIs Seguras: Evitar APIs inseguras como innerHTML e usar alternativas como textContent.
XSS é uma das vulnerabilidades mais comuns na web e está listado no OWASP Top 10.
Abaixo estão exemplos de falhas e correções para Cross-Site Scripting (XSS) em Java e JavaScript.
Exemplo de Falha de XSS Refletido em Java
Imagine uma aplicação web onde os dados do usuário são incluídos diretamente na resposta sem validação ou sanitização.
// Controlador Java usando Servlets
import javax.servlet.http.*;
public class XSSExample extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String name = request.getParameter("name");
response.setContentType("text/html");
response.getWriter().println("<h1>Olá, " + name + "!</h1>");
}
}
// Se o atacante enviar name=<script>alert('XSS')</script>, o navegador executará o script malicioso.
Correção em Java
- Sanitizar Saída: Use bibliotecas como OWASP Java Encoder:
import org.owasp.encoder.Encode;
public class SecureXSSExample extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String name = request.getParameter("name");
response.setContentType("text/html");
response.getWriter().println("<h1>Olá, " + Encode.forHtml(name) + "!</h1>");
}
}
- Validar Entrada utilizando Regex ou bibliotecas como Hibernate Validator para aceitar apenas valores válidos.
if (!name.matches("[a-zA-Z0-9 ]+")) {
throw new IllegalArgumentException("Nome inválido");
}
Exemplos da falha em JavaScript
Imagine um sistema onde comentários são salvos e exibidos sem sanitização. Código Backend:
const express = require('express');
const app = express();
let comments = [];
app.use(express.urlencoded({ extended: true }));
app.post('/comment', (req, res) => {
comments.push(req.body.comment); // Armazena sem sanitização
res.send("Comentário adicionado!");
});
app.get('/comments', (req, res) => {
res.send(`
<h1>Comentários:</h1>
${comments.map(c => `<p>${c}</p>`).join('')}
`);
});
// Um atacante pode enviar um comentário como <script>alert('XSS')</script>, que será executado para todos os usuários.
Correção em JavaScript
- Sanitizar Saída utilizando bibliotecas como DOMPurify para limpar dados antes de renderizá-los.
Exemplo com DOMPurify:
const DOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const window = new JSDOM('').window;
const purify = DOMPurify(window);
app.get('/comments', (req, res) => {
res.send(`
<h1>Comentários:</h1>
${comments.map(c => `<p>${purify.sanitize(c)}</p>`).join('')}
`);
});
- Escape Manual: Converta caracteres perigosos para entidades HTML.
function escapeHtml(str) {
return str
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
app.get('/comments', (req, res) => {
res.send(`
<h1>Comentários:</h1>
${comments.map(c => `<p>${escapeHtml(c)}</p>`).join('')}
`);
});
- Usar Bibliotecas de Templates Seguras: Frameworks como React ou Angular automaticamente escapam conteúdo, prevenindo XSS:
const CommentList = ({ comments }) => (
<div>
{comments.map((comment, index) => (
<p key={index}>{comment}</p> // React escapa automaticamente
))}
</div>
);
Boas Práticas Gerais
- Nunca confiar na entrada do usuário: Sempre validar e sanitizar.
- Escapar dados ao renderizar: Use ferramentas específicas para cada linguagem ou framework.
- Bibliotecas confiáveis:
- Java: OWASP Java Encoder.
- JavaScript: DOMPurify ou frameworks modernos como React, Angular e Vue.js.
- Cuidado com APIs DOM: Manipulações como innerHTML são perigosas. Prefira APIs seguras, como textContent:
element.textContent = userInput;