Porque é que estão aqui?
Já ouviu falar de ataques de injeção de SQL em JavaScript, mas não tem a certeza absoluta de como são na prática ou se precisa de se preocupar com eles. Talvez esteja a tentar perceber o quão grave pode ser.
Em suma, se está a criar aplicações que utilizam bases de dados SQL, como MySQL e PostgreSQL, está em risco - não está a salvo dos métodos de ataque que assolam os programadores e as suas bases de dados há décadas. Como programador, a responsabilidade recai sobre si para implementar guardrails que protejam os dados do utilizador e garantir que a sua infraestrutura subjacente nunca é invadida, explorada ou comandada.
Todas as novas ferramentas dizem que o estão a ajudar, mas apenas tornam o desenvolvimento mais complexo.
Pode adicionar um mapeador objeto-relacional (ORM) como o Sequelize e o TypeORM para simplificar a forma como trabalha com bases de dados SQL como o MySQL e o PostgreSQL, mas não o isentam completamente de riscos. As firewalls de aplicações Web (WAFs) ajudam a bloquear ataques ao nível da rede, mas requerem infra-estruturas dispendiosas e manutenção constante. Os scanners de código podem ajudá-lo a identificar falhas óbvias, mas fazem muito menos pelas incógnitas desconhecidas e pelas técnicas de dia zero à espreita.
Vamos apresentar-lhe uma imagem clara do aspeto dos ataques de injeção de SQL, do risco que representam e dos erros de desenvolvimento que os tornam possíveis. Depois, faremos melhor, guiando-o na instalação de um hotfix global para que saiba, com certeza, que as suas aplicações estão seguras.
Ataques de injeção de SQL: exemplos e implicações
A definição mais básica de um ataque de injeção de SQL é quando uma aplicação permite que a entrada do utilizador não validada e não higienizada execute consultas à base de dados, permitindo que um atacante leia a base de dados SQL, modifique registos ou elimine o que lhe apetecer.
Como é habitual, o XKCD ilustra o perigo da SQL melhor do que a maioria dos cenários sombrios que poderíamos imaginar:

Qual é o aspeto de uma aplicação JavaScript vulnerável?
Vamos começar com um exemplo simples de pseudocódigo: uma aplicação JavaScript com um elemento de entrada que permite aos utilizadores pesquisar uma base de dados de gatos. No exemplo de código JavaScript abaixo, a aplicação responde a pedidos POST no caminho /cats para extrair a entrada do utilizador do corpo do pedido e liga-se à base de dados com uma consulta para devolver todos os gatos com um ID correspondente. Em seguida, a aplicação apresenta o gato utilizando a resposta JSON.
app.post("/cats", (request, response) => {
const query = `SELECT * FROM cats WHERE id = ${request.body.id}`;
connection.query(query, (err, rows) => {
if(err) throw err;
response.json({
data: rows
});
});
});
Embora este exemplo possa parecer inócuo para quem não tem formação em ataques de injeção SQL, é extremamente vulnerável. Nomeadamente, a aplicação não tenta validar ou higienizar a entrada do utilizador para sequências ou métodos de codificação potencialmente perigosos econcatenaa entrada do utilizador diretamente na consulta SQL, o que permite aos atacantes múltiplas oportunidades de atacar utilizando métodos de ataque de injeção SQL comuns que existem há décadas.
Exemplo de cargas úteis de ataque JavaScript SQL
A injeção de SQL baseia-se em enganar a sua base de dados MySQL ou PostgreSQL para que tome medidas ou responda com dados fora do âmbito esperado devido à forma como a sua aplicação gera consultas SQL.
O 1=1 é sempre verdadeiro ataque pode devolver toda a tabela de gatos com truques como apóstrofos ou aspas, porque 1=1
é de facto sempre VERDADEIRO:
- O utilizador introduz os dados:
BOBBY TABLES" OU 1='1
- A base de dados executa a consulta SQL:
SELECT * FROM Users WHERE Cat = BOBBY TABLES OR 1=1;
Da mesma forma, os atacantes podem explorar um = é sempre verdade ataque para devolver todos os gatos, porque ""=""
é sempre VERDADEIRO:
- O utilizador introduz os dados:
" OU ""="
- A base de dados executa a consulta SQL:
SELECT * FROM Cats WHERE CatId ="" or ""="";
Os atacantes exploram frequentemente a forma como as bases de dados tratam os comentários em linha e, ao inserirem comentários (/* ... */)
numa consulta, podem ofuscar a sua intenção ou contornar filtros.
- O utilizador introduz os dados:
DR/*hello world*/OP/*sneak attack*/ TABLE Cats;
- A base de dados executa a consulta SQL:
DROP TABLE Cats;
Outra estratégia comum de injeção SQL em JavaScript é o empilhamento de consultas, que permite que os atacantes comecem com uma cadeia inócua e, em seguida, utilizem um ponto e vírgula (;) para terminar essa declaração e iniciar outra que contenha a sua injeção. Os atacantes utilizam frequentemente o empilhamento de consultas para eliminar bases de dados inteiras de uma só vez com um comando DROP TABLE:
- O utilizador introduz os dados:
Bobby; DROP TABLE Cats --
- A aplicação constrói a sua consulta SQL:
const query = "SELECT * FROM Cats WHERE CatId = " + input;
- A base de dados executa a consulta SQL:
SELECT * FROM Cats WHERE CatId = BOBBY; DROP TABLE Cats;
E quanto aos ataques de injeção NoSQL?
Os ataques de injeção NoSQL são igualmente perigosos para a segurança da sua aplicação e dos dados do utilizador, mas apenas afectam as pilhas de tecnologia que utilizam bases de dados como o MongoDB. A principal diferença são os ataques de estilo, uma vez que as consultas SQL e NoSQL utilizam uma sintaxe totalmente única que não se traduz de uma categoria para a outra.
Se estiver a utilizar uma base de dados SQL, não corre o risco de sofrer ataques de injeção NoSQL e vice-versa.
O caminho básico: corrigir manualmente todas as suas vulnerabilidades de injeção de SQL
Nesta altura, poderá estar menos interessado em saber quais são os possíveis truques de injeção e mais interessado em saber como proteger os dados que tem no MySQL ou PostgreSQL.
- Utilizar consultas parametrizadas: O SQL tem a funcionalidade de desligar a execução de consultas e valores, protegendo a base de dados de ataques de injeção. Com o exemplo JavaScript/Node.js acima, pode utilizar um marcador de posição na sua consulta SQL com um ponto de interrogação (
?
). Oconexão.consulta()
recebe então o parâmetro no seu segundo argumento, fornecendo os mesmos resultados num método à prova de injeção.
app.post("/cats", (request, response) => {
const query = `SELECT * FROM Cats WHERE id = ?`;
const value = request.body.id;
connection.query(query, value, (err, rows) => {
if(err) throw err;
response.json({
data: rows
});
});
});
- Validar e higienizar a entrada do utilizador: Embora as consultas parametrizadas possam ajudar a proteger a sua base de dados SQL contra intrusões e ataques, também pode impedir que os utilizadores introduzam cadeias de caracteres potencialmente perigosas na sua aplicação.
Uma opção é adicionar bibliotecas de código aberto para sanitização e validação à sua aplicação. Por exemplo, você pode usar validador.js no ecossistema JavaScript/Node.js para verificar se um utilizador está a tentar introduzir um endereço de e-mail real - e não um ataque de injeção de SQL - no seu formulário de inscrição.
Também pode desenvolver validadores personalizados baseados em regex para efetuar um trabalho semelhante, mas terá pela frente um caminho extremamente moroso e complexo, com pesquisas e toneladas de testes manuais. Além disso, consegue mesmo interpretar este exemplo de regex para validação de correio eletrónico?const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
A mesma ideia aplica-se à prevenção de cadeias de caracteres como..." OU 1-'1.
Pode tentar investigar e eliminar todas estas oportunidades, mas provavelmente preferiria passar o seu tempo a criar novas funcionalidades.
- Implantar WAFs ou plataformas de segurança baseadas em agentes: Embora essas soluções possam bloquear ataques de SQL antes mesmo que eles toquem seu aplicativo ou, pelo menos, notificá-lo em tempo real à medida que os ataques acontecem, elas vêm com algumas ressalvas.
Primeiro, elas geralmente são caras e exigem que você inicie uma nova infraestrutura no local ou na nuvem, que geralmente é muito mais complexa do que a que você assinou como um desenvolvedor que só quer enviar para a produção. Em segundo lugar, exigem mais manutenção manual para atualizar o conjunto de regras, distraindo-o de outras intervenções manuais para a injeção de SQL. Por último, adicionam frequentemente mais carga computacional ou redireccionam todos os pedidos através da sua plataforma para análise, aumentando a latência e prejudicando a experiência do utilizador final.
O grande problema é que as oportunidades de ataques de injeção de SQL são como ervas daninhas - pode cortá-las todas uma vez utilizando estas ferramentas, mas tem de estar constantemente atento a toda a sua base de código para garantir que nunca mais brotam.
Um caminho alternativo para resolver ataques de injeção de SQL em JavaScript: Firewall Aikido
A Aikido Security lançou recentemente o Firewall, um motor de segurança gratuito e de código aberto que o projecta de forma autónoma contra ataques de injeção de SQL - e muito mais.
Se você não estiver usando Node.js, saiba que começaremos a oferecer suporte a outras linguagens e estruturas no futuro. Pode sempre subscrever a nossa newsletter de produtos para saber exatamente quando a Firewall se expandir para além do mundo do JavaScript ou enviar-nos um e-mail para hello@aikido.dev se quiser lançar uma linguagem específica.
Testar uma aplicação que é vulnerável à injeção de SQL do JavaScipt
Vamos usar um aplicativo de amostra que vem com o repositório de código aberto para mostrar como o Aikido Firewall funciona. Também vai precisar do Docker/DockerCompose para implementar uma base de dados MySQL local.
Comece por bifurcar o repositório firewall-node e clonar essa bifurcação para a sua estação de trabalho local.
git clone https://github.com/<YOUR-GITHUB-USERNAME>/firewall-node.gitcd firewall-node
Use o Docker para implantar um banco de dados MySQL local na porta 27015. Este ficheiro docker-compose.yml também cria contentores s3mock, MongoDB e PostgreSQL, uma vez que foi criado para ajudar a equipa Aikido a testar como a Firewall bloqueia vários ataques.
docker-compose -f sample-apps/docker-compose.yml up -d
Em seguida, inicie a aplicação de amostra:
node sample-apps/express-mysql2/app.js
Aberto http://localhost:4000
no seu browser para ver a aplicação muito simples para gatos. Na área de texto, escreva alguns nomes de gatos e clique no botão Adicionar botão. Para testar a injeção de SQL, pode clicar no botão Injeção de teste ligação ou escreva o seguinte na área de texto: Kitty'); DELETE FROM cats;-- H
e clique em Adicionar novamente. De qualquer forma, a aplicação permite empilhar várias consultas em conjunto utilizando alguns comentários de consulta furtivos, eliminando toda a base de dados de gatos.
Como é que isto acontece? Tal como avisámos anteriormente, esta aplicação simplesmente acrescenta qualquer a entrada do utilizador no final da consulta SQL, que é inerentemente insegura.
const query = `INSERT INTO cats(petname) VALUES ('${name}');`
As consequências podem ser pequenas, mas não é difícil imaginar como este erro, muitas vezes honesto, pode ter consequências desastrosas para a sua aplicação de produção.
Bloqueio da injeção de SQL em JavaScript com a Aikido Firewall
Vejamos agora a rapidez com que o nosso motor de segurança de código aberto bloqueia ataques de injeção de SQL em JavaScript sem ter de corrigir manualmente cada interação com a base de dados no seu código.
Se ainda não tem uma conta Aikido, vá em frente e fazer um gratuitamente. Se já tiver um, inicie sessão e ligar a sua conta GitHub. Durante esse processo, conceda à Aikido acesso para ler a sua bifurcação do nó de firewall
projeto.
Ir para o Painel de controlo da firewall e clique em Adicionar serviço. Dê um nome ao seu serviço e, mais uma vez, escolha o seu fork para o nó de firewall
projeto.

O Aikido então instrui-o sobre como instalar e implementar o Aikido Firewall. Como estamos a usar a aplicação de exemplo, esse trabalho já está feito para si, mas é uma referência útil para saber como levar o nosso motor de segurança de código aberto a todas as suas aplicações Node.js que possam estar vulneráveis a ataques de injeção de SQL em JavaScript.

Clique no botão Gerar Token para criar um token para permitir que a Aikido Firewall transmita de forma segura informações sobre ataques de injeção de SQL bloqueados para a plataforma de segurança Aikido. Copie o token gerado, que começa com AIK_RUNTIME...
e volte ao terminal para executar novamente a aplicação de amostra, mas agora com o Firewall totalmente ativado no modo de bloqueio:
AIKIDO_TOKEN=<YOUR-AIKIDO-TOKEN> AIKIDO_DEBUG=true AIKIDO_BLOCKING=true node sample-apps/express-mysql2/app.js
Aberto localhost:4000
e, mais uma vez, invocar o ataque de injeção de SQL incluído. Desta vez, o Aikido bloqueia-o no browser, envia para os registos do seu servidor Web local e gera um novo evento. Clique nele para ver detalhes abrangentes sobre a tentativa de injeção de SQL, incluindo o payload e onde a sua aplicação gerou a perigosa consulta SQL.

Em vez de se preocupar em proteger para sempre as suas aplicações contra ataques de injeção de SQL JavaScript, tanto críticos como ainda não vistos, a Aikido Firewall oferece um bloqueio abrangente e uma observabilidade sofisticada que o mantém informado sobre fontes de ataque, cargas úteis comuns e potenciais pontos fracos.
O que é que se segue?
Pode instalar e implementar a Aikido Firewall em todas as suas aplicações baseadas em Node.js gratuitamente. O nosso motor de segurança incorporado de código aberto protege a sua infraestrutura e os dados dos utilizadores contra ataques de injeção de SQL em JavaScript, injeção de comandos, poluição de protótipos, passagem de caminhos e muito mais, que será apresentado em breve.
Não estamos dizendo que o Firewall deve substituir as práticas recomendadas de desenvolvimento para proteção contra injeção de SQL, como o uso de consultas parametrizadas ou nunca confiar na entrada do usuário, mas também sabemos por experiência própria que nenhum desenvolvedor é perfeito. Nenhuma base de código é sem falhas, e erros honestos acontecem o tempo todo.
Pense no Firewall como um hotfix global para injeção de SQL. Ao contrário do regex desenvolvido sob medida, WAFs que induzem latência ou agentes de segurança complexos que custam um belo centavo, ele faz esse trabalho extraordinariamente bem e com impacto insignificante - inteiramente de graça.
Se gostou do que viu, consulte o nosso roteiro e dê uma estrela ao nosso repositório GitHub(https://github.com/AikidoSec/firewall-node). ⭐