Cada linguagem de programação vem com seu próprio conjunto de vulnerabilidades de segurança, e o JavaScript não é uma exceção. Explorar vulnerabilidades do JavaScript pode levar à manipulação de dados, sequestro de sessão, acesso não autorizado a dados e muito mais. Embora comumente associados à funcionalidade do lado do cliente, os riscos de segurança do JavaScript também podem representar ameaças significativas em ambientes do lado do servidor.
Para qualquer aplicativo, a confiança do cliente é muito importante. Manter essa confiança requer proteger os dados do cliente e garantir a segurança dos aplicativos. Felizmente, implementar salvaguardas adequadas pode mitigar esses riscos e melhorar a segurança de sua aplicação.
Neste artigo, vamos explorar algumas das ameaças de segurança do JavaScript mais comuns e discutir ferramentas e estratégias eficazes para proteger seu aplicativo de possíveis ataques.
Cross-Site Scripting
Cross-site scripting (XSS) é uma exploração de segurança que permite a um invasor injetar código malicioso do lado do cliente em um site. De acordo com o Projeto de Segurança de Aplicativos Web Abertos (OWASP) Top 10 segurança vulnerabilidades em 2021, o XSS ocupa o terceiro lugar como vetor de ataque mais comum.
Como Mitigar o XSS
Validação de Entrada
Garanta que a entrada do usuário siga os tipos de dados, formatos e intervalos esperados. Remova ou escape caracteres potencialmente prejudiciais para evitar injeções.
function validateInput(input) {
return input.replace(/[^a-zA-Z0-9]/g, ''); // Allow only alphanumeric characters
}
Codificação de Saída
Converta os caracteres especiais na saída para seus equivalentes de entidades HTML para neutralizar scripts potencialmente maliciosos antes de renderizá-los.
function encodeHTML(input) {
return input.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
Clickjacking
Clickjacking é um ataque enganoso que engana os usuários a clicarem em um elemento com o qual não pretendem interagir. Essa técnica envolve a incorporação de um site legítimo dentro de um malicioso — frequentemente usando um HTML <iframe>
invisível ou posicionado de forma enganosa — para se apropriar das ações do usuário. Como resultado, os atacantes podem roubar credenciais de login, obter permissões não autorizadas ou até mesmo enganar os usuários para instalar malware sem saber.
Uma maneira comum de conseguir isso é usar CSS para adicionar um botão sobreposto que tem a propriedade opacity
configurada para quase 0. Isso engana o usuário a clicar em um botão ou link não intencional.
Como Prevenir o Clickjacking
O X-Frame-Options instrui o navegador se o site pode ser incorporado dentro de um iframe. Ele tem três opções:
- DENY – Impede que a página seja exibida em um iframe completamente
- SAMEORIGIN – Permite que a página seja incorporada apenas se a solicitação se originar do mesmo domínio
- ALLOW-FROM – Permite que a página seja incorporada apenas por um domínio específico e confiável
No Node.js, você pode usar helmet
para configurar essas opções como mostrado abaixo:
const helmet = require("helmet");
const app = express();
app.use(
helmet({
xFrameOptions: { action: "sameorigin" },
}),
);
Uma defesa eficaz contra o clickjacking é implementar o cabeçalho Content Security Policy (CSP). O CSP fornece controle granular sobre como e onde o conteúdo pode ser incorporado, impedindo o enquadramento não autorizado.
Para mitigar os riscos de clickjacking, inclua a diretiva frame-ancestors
em seu cabeçalho CSP. Por exemplo:
Content-Security-Policy: frame-ancestors 'self' https://www.example.org;
Esta política garante que o documento protegido só pode ser incorporado por sua própria origem ('self'
) e domínios explicitamente permitidos, como example.org
. Ele bloqueia todas as tentativas não autorizadas de enquadrar o conteúdo, protegendo os usuários de ataques de clickjacking.
Nota: Se frame-ancestors e X-Frame-Options estiverem ambos configurados, então os navegadores que suportam frame-ancestors vão ignorar X-Frame-Options.
Ataque de Falsificação de Solicitação entre Sites (CSRF)
CSRF (às vezes também chamado de XSRF) explora a confiança que um site tem no navegador do usuário ao fazer solicitações não autorizadas em nome do usuário. Os atacantes enganam os usuários para executar ações sem o conhecimento deles, potencialmente levando a violações de dados ou transações indesejadas. Alguns exemplos são atualizar os detalhes pessoais da vítima, iniciar uma transferência de fundos da conta bancária da vítima ou até redirecionar uma entrega de pacote para um endereço diferente.
Vamos analisar um exemplo específico disso. Você está visitando o site do seu banco e fez login. Digamos que você receba um e-mail de promoção fingindo ser do seu banco. O link te leva para uma página aparentemente inofensiva. Nos bastidores, uma solicitação POST é acionada e enviada para o aplicativo bancário legítimo.
curl --location --request POST 'https://acmebank.com/transfer?routing=852363&fromAccountNumber=123456789&toAccountNo=987654321' \
--header 'Cookie: session=acmebanksessionvalue'
Do lado do aplicativo acmebank.com, a tag “script” envia o formulário assim que o usuário carrega a página, sem validação do usuário ou o usuário perceber o que está acontecendo, como mostrado abaixo.
<html>
<body>
<form action="https://acmebank.com/transfer" method="POST">
<input type="hidden" routing="852363" fromAccountNo="123456789" toAccountNo="987654321" amount="5000" />
</form>
<script>
window.addEventListener("DOMContentLoaded", () => {
document.querySelector("form").submit();
});
</script>
</body>
</html>
O formulário acima cria a seguinte solicitação para o aplicativo real, acmebank. A solicitação contém o cookie de sessão do usuário legítimo, mas contém o número da nossa conta bancária! Como sua sessão com seu banco ainda está ativa, a transferência do valor será concluída se não houver outra validação em vigor.
Como se Defender Contra CSRF
Defina o atributo SameSite como Strict. Isso controla se um cookie é enviado com solicitações entre sites.
- Esses cookies de sessão devem ter uma vida útil curta. Exija reautenticação para ações sensíveis para mitigar riscos.
Use tokens únicos de sessão CSRF. Este token pode então ser incluído dentro de um formulário que é enviado pelo navegador. Para cada solicitação, o servidor compara o token enviado pelo cliente com seu valor armazenado para a sessão. Use a biblioteca csrf-csrf para configurar tokens únicos.
Roubo de Dados de Sessão
O sequestro de sessão ocorre quando um atacante rouba o token de sessão de um usuário, permitindo que ele se passe pelo usuário e obtenha acesso não autorizado à sua conta.
Como Prevenir o Sequestro de Sessão
Use Cookies Seguros
Defina as flags Secure
e HttpOnly
nos cookies de sessão para evitar acesso não autorizado. Definir o atributo Secure impede que o cookie de sessão seja transmitido em texto claro e permite que ele seja transmitido apenas por conexões HTTPS. Definir o atributo Http-Only
obriga o navegador a não permitir acesso ao cookie a partir do DOM o que impede que ataques baseados em scripts do lado do cliente acessem os dados sensíveis armazenados nesses cookies.
Ativar Autenticação Multifator (MFA)
Adicione uma camada extra de segurança para verificar usuários. Este é um método muito comum que você encontrará na maioria das aplicações seguras. Integrações fáceis estão disponíveis através de provedores como Okta e Duo.
Implementar Expiração de Sessão
Expirar automaticamente sessões inativas para reduzir janelas de ataque.
Práticas de Codificação e Ferramentas para Segurança de Alto Nível
Varredura de Vulnerabilidades
Um scanner de vulnerabilidades mantém a segurança de sua aplicação. A digitalização de suas bibliotecas, rede, aplicativos e dispositivos ajuda a descobrir falhas que os atacantes poderiam explorar. Ferramentas como Snyk e Sonarqube podem ser facilmente integradas em bases de código JavaScript. Essas ferramentas trabalham em paralelo com listas conhecidas de vulnerabilidades mantidas pela OWASP. Com integração perfeita como parte do processo de desenvolvimento, esses scanners fornecem aos desenvolvedores e equipes de segurança visibilidade em tempo real e precisa sobre as vulnerabilidades de código e soluções para corrigi-las.
Testes de Penetração e Avaliações
Os desenvolvedores podem adotar práticas de teste de penetração para sondar e explorar ativamente possíveis vulnerabilidades dentro de uma aplicação. Hackers éticos simulam ataques do mundo real para avaliar a postura de segurança de aplicações web manipulando o código JavaScript e interações do usuário.
Para realizar isso, os desenvolvedores podem escrever código JS personalizado para simular os cenários, ou podem utilizar ferramentas especializadas de teste de penetração que utilizam JavaScript para automatizar o processo de varredura em busca de vulnerabilidades comuns como XSS, utilizando o OWASP ZAP. Mais informações sobre teste de penetração estão disponíveis no guia oficial da OWASP.
Firewall de Aplicação Web (WAF)
À medida que as aplicações crescem, o tráfego web também aumenta, aumentando a exposição a ataques. Implementar um Firewall de Aplicação Web (WAF) ajuda a proteger contra tráfego malicioso filtrando e monitorando solicitações HTTP. Isso envolve a integração com fornecedores de WAF de terceiros, como Cloudflare ou AWS WAF. Com o WAF, você pode definir regras como:
- País ou localização geográfica de onde as solicitações se originam.
- Endereço IP, intervalo CIDR e nomes de domínio de onde as solicitações se originam.
- Limitar o comprimento das solicitações e parâmetros de consulta para evitar ataques de injeção.
- Códigos SQL que provavelmente são maliciosos. Os atacantes tentam extrair dados de seu banco de dados inserindo códigos SQL maliciosos em uma solicitação web. Isso é conhecido como injeção de SQL.
- Detectar e bloquear scripts incorporados que podem fazer parte de ataques XSS.
Um WAF também pode ajudar a mitigar Denial of Service Distribuído (DDoS) ataques, garantindo a disponibilidade da aplicação.
Proteger a Integridade dos Dados
Implementar medidas robustas de integridade dos dados é essencial ao armazenar ou acessar informações seguras. As melhores práticas incluem:
- Impor políticas de senhas fortes e incentivar o uso de gerenciadores de senhas. Além disso, incentive seus usuários a usar um gerenciador de senhas para que possam usar senhas mais complexas e não precisem se preocupar em lembrá-las (Use LastPass ou 1Password).
- Proteger contra ataques de força bruta em páginas de login com limitação de taxa, bloqueios de conta após um certo número de tentativas malsucedidas e desafios CAPTCHA.
- Usando cabeçalhos HTTP como:
- HTTP Access-Control-Allow-Origin para controlar quais origens podem acessar recursos.
- HTTP X-Content-Type-Options para prevenir riscos de segurança de tipo MIME.
- Integridade de subrecursos (SRI) para garantir que recursos de CDNs não sejam alterados.
Conclusão
A segurança do JavaScript é um processo contínuo que requer uma abordagem proativa para proteger aplicações contra ameaças em evolução. Implementar melhores práticas, como validação de entrada, cabeçalhos CSP, gerenciamento seguro de sessões e varredura de vulnerabilidades, pode reduzir significativamente o risco de ataques como XSS, CSRF e sequestro de sessão.
Além disso, utilizar ferramentas de segurança como WAFs, testes de penetração e MFA fortalece a resiliência da aplicação. Priorizar a segurança em cada etapa do desenvolvimento permitirá que os desenvolvedores construam aplicações robustas e dignas de confiança dos usuários que permaneçam protegidas contra ameaças cibernéticas modernas.
Source:
https://dzone.com/articles/enhancing-security-in-javascript