O JavaScript é uma das linguagens de programação mais utilizadas para o desenvolvimento de aplicações web, além de estar se tornando cada vez mais comum em aplicações mobile. Segundo dados do Stack Overflow, quase 70% das pessoas desenvolvedoras programam em JavaScript. Por isso, neste artigo, exploramos algumas das técnicas de codificação segura para JavaScript, destacando o papel das pessoas desenvolvedoras como protagonistas em prevenir vulnerabilidades e potenciais ameaças ao seu software.
Sua popularidade o torna um dos alvos principais para criminosos cibernéticos. A organização Secure Coding mostra que o JavaScript está na quarta posição na lista das linguagens de programação mais vulneráveis, atrás apenas das linguagens Java, PHP e C. Sabendo disso, é fundamental que os devs que utilizam essa linguagem no seu cotidiano de desenvolvimento sejam proativos na adoção de medidas de segurança e proteção para o código da aplicação.
Como funciona o JavaScript
JavaScript é uma linguagem de gerenciamento de memória. Isto é, ao criar funções, variáveis, strings e etc, o mecanismo aloca uma certa quantidade de memória e a libera por conta própria quando não é mais necessária. O JavaScript faz esse processo automaticamente para você!
Assim, quando a reserva for liberada (Release), a memória pode ser utilizada para outras finalidades. Para esse propósito, existe um coletor de lixo que em segundo plano recupera a memória alocada. Assim, este coletor de lixo remove alguns objetos quando eles se tornam inacessíveis.
Esse ciclo de vida da memória no JavaScript evita que você encontre os problemas clássicos de estouro de buffer, um transbordamento de dados, como nas linguagens C e C++. No entanto, existem muitas maneiras pelas quais o código escrito nesta linguagem pode ser vulnerável a ataques muito comuns como SQL Injection e Cross-Site Scripting.
Evite ataques de Cross-Site Scripting (XSS)
Cross-site scripting (XSS) ocorre quando o invasor injeta código malicioso no lado do cliente de uma aplicação web, geralmente na forma de um script no navegador. As falhas permitem que o navegador aceite esses dados não confiáveis sem validá-los adequadamente, possibilitando que o invasor possa acessar quaisquer cookies, tokens de sessão ou outras informações confidenciais retidas pelo navegador e usadas com esse site.
Para evitar esse tipo de ameaça, recomendamos as seguintes práticas:
Sempre valide e limpe a entrada dos usuários.
Garantindo, assim, que ela contenha apenas o caracteres aceitáveis que não possam ser utilizados para iniciar ataques do tipo XSS.
Utilize métodos seguros como o innerText em vez do innerHTML
Para manipular o Document Object Model (DOM), utilize métodos seguros como o innerText em vez do innerHTML, evitando o XSS baseado em DOM. O innerHTML geralmente é usado para inserção de tags, textos e imagens em uma página web, gerando um risco de segurança, por esta razão, não se utiliza o innerHTML para inserção de texto puro.
Entendendo na prática por meio do seguinte exemplo, criando uma propriedade:
Exemplo utilizando innerHTML:
Resultado utilizando innerHTML:
Exemplo utilizando innerText:
O resultado utilizando innerText:
Em suma, o innerText recupera e define o conteúdo da tag como texto simples, enquanto innerHTML recupera e define o conteúdo em formato HTML.
Utilize estruturas e funções que ajudam a prevenir ataques XSS
O Node.Js, compilação empacotada do mecanismo JavaScript V8 do Google, possui as funções globais encodeURI e encodeURIComponent que podem te ajudar nisso. Além disso, é importante considerar o uso de pacotes como o XSS-Filters.
É seguro aplicar esses filtros assim:
document.write(“<a href=” + xssFilters.uriInUnQuotedAttr(url) + “>” + xssFilters.uriInHTMLData(url) + “</a>”);
Os filtros XSS são projetados principalmente com base na especificação HTML 5 . O princípio é escapar de caracteres específicos para cada contexto de saída não programável.
No lado do servidor (Node.js), instale o xss-filters npm e inclua-o como uma dependência para seu projeto:
npm install xss-filters –save
No próprio repositório do XSS-Filters existem tutoriais mais avançados, além de explicar como instalá-lo no lado do cliente (navegador)
Evite ataques de SQL Injection
Um ataque de SQL Injection consiste na “injeção” de uma consulta SQL por meio de dados de entrada do cliente na aplicação. Uma exploração bem-sucedida permite ao invasor ler dados confidenciais do banco de dados, além de modificá-los.
No caso do Javascript, os bancos de dados SQL são vulneráveis a esse tipo de ataque se os parâmetros de consulta forem facilmente explorados pela execução de instruções arbitrárias.
Para evitar esse tipo de ameaça, recomendamos as seguintes práticas:
Realize a validação de entrada do usuário de forma adequada
Vejamos esse exemplo do uso do framework Express.Js (ou só Express), um dos mais utilizados em conjunto com o Node.Js, na apresentação de uma vulnerabilidade para esse tipo de ataque:
Nesse caso, a aplicação obtém IDs de usuário dessa URL e recupera o endereço de e-mail correspondente através da consulta do banco de dados, pois existem duas brechas nesse trecho de código:
A primeira delas, é que a consulta ao banco de dados foi construída utilizando a concatenação de strings.
A segunda brecha ocorre na entrada do usuário ser concatenada à consulta em vez de ser tratada como dados não confiáveis.
Um invasor pode criar um parâmetro de ID de string de consulta de forma que possa acessar todas as tabelas do banco de dados da aplicação. Inserindo, por exemplo, estes parâmetros de string:
Resultando na seguinte consulta:
Uma consulta bem-sucedida fornecerá ao invasor uma lista de todas as tabelas do banco de dados. Portanto, para mitigar SQL Injection, desenvolvedores precisam sempre realizar a validação de entrada apropriada, pois se a verificação de validação falhar, a consulta SQL não será executada.
Utilize consultas parametrizadas ou instruções preparadas em vez de concatenações
Nesse caso, as consultas parametrizadas servem para abstrair a sintaxe SQL dos parâmetros de entradas. O exemplo em Node.Js abaixo mostra o código de uma autorização, em que o nome de usuário e a senha sairão da solicitação HTTP. O sqlQuery contém uma consulta que foi criada para autenticar as credenciais de entrada.. A consulta SQL é executada na linha 6 como é possível verificar:
A falha nesse código é a consulta SQL e a falta de higienização de nome de usuário e senha, as entradas. Nesse caso, uma instrução preparada ou consulta parametrizada deve ser usada em vez de concatenação. Uma instrução preparada serve para abstrair a sintaxe SQL de quaisquer parâmetros de entrada.
Exemplo utilizando instrução preparada:
Para entender mais sobre instruções preparadas em JavaScript, confira este documento.
Seja crítico com componentes de terceiros
Aplicações dessa linguagem são altamente dependentes de bibliotecas de terceiros. E esses componentes também podem conter vulnerabilidades ou conteúdo com intencionalidade duvidosa, afetando a segurança de sua aplicação.
Sempre inspecione bibliotecas de terceiros para encontrar vulnerabilidades:
Adicione um código de integridade para sua aplicação
Atuando na parte front-end, é provável que você tenha utilizado tags para importar bibliotecas de terceiros. Mas e se o recurso tiver sido adulterado? Isso é algo possível de ocorrer quando você renderiza recursos externos para sua aplicação web, causando perda de segurança em sua aplicação.
Para lidar com essa situação, você pode adicionar um código de integridade, conhecido como Subresource Integrity (SRI) para que os navegadores verifiquem se os recursos, como Content Delivery Network (CDNs) que eles buscam, são entregues sem manipulação inesperada. Ele funciona permitindo que você forneça um hash criptográfico que um recurso buscado deve corresponder.
Vale lembrar que, antes de avaliar se foi adulterado, ainda é necessário garantir que o código externo que você está utilizando não contenha vulnerabilidades.
Atualize as versões de pacote NPM
Se você identificar algum símbolo como ^ou ~ em qualquer versão do pacote NPM, significa que existe uma versão automática para versões secundárias e de patch.
Ativando a atualização desses pacotes ajudará a reduzir os riscos de segurança.
Utilize algum gerenciador de pacotes
Rastrear todos os pacotes que está utilizando em sua aplicação web pode te ajudar a manter as vulnerabilidades de terceiros controladas.
É possível realizar isso por meio de um gerenciador de pacotes como npm, Yarn ou pnpm. Além de gerenciar, eles também fornecem ferramentas para auditar seus pacotes e ajudar a encontrar problemas comuns de segurança em JavaScript.
Importância da capacitação em Codificação Segura para desenvolvedores
Existem muitos outros problemas comuns de segurança em JavaScript que podem aumentar o risco para a sua aplicação. Além de que, vulnerabilidades novas estão sempre surgindo e, por isso, quem desenvolve precisa estar atualizado e por dentro dessas técnicas de codificação segura.
Quando olhamos um processo de desenvolvimento desenhado, identificamos que a primeira etapa é o treinamento e capacitação nesse tipo de habilidade.
Fica claro que esse tipo de atividade é essencial para o processo de Desenvolvimento Seguro. Com o People & Culture, módulo Education, da Conviso Platform, é possível realizar exercícios técnicos de codificação segura em JavaScript e muitas outras linguagens.
Post original: https://bit.ly/3yMjtKO
Através do People & Culture, você pode solucionar desafios do mundo real de segurança e ainda receber pontuações para acompanhar sua evolução.
Top comments (0)