Executando verificação de segurança...
1

Por que eval() é tão perigoso?

A FUNÇÃO EVAL

A função eval() dentro do javascript é uma função que avalia uma expressão enviada como string por parâmetro a ela, portanto, o que vier dentro dela será executado.

Por exemplo, se caso enviarmos como parâmetro "1 + 1" como string, a função irá avaliar essa expressão e retornará seu resultado, que no caso será o numero 2!

Essa função serve também para fazermos um parse de valores recebidos como parâmetro e vamos ver isso em um exemplo prático.

const express = require('express')

express().get('/number', async(req, res) => {
    const numberOne = eval(req.query.numberOne)
    const numberTwo = eval(req.query.numberTwo)

    const response = numberOne * numberTwo
    
    res.end(`response number: ${response}`)
})

.listen(3000, () => console.log('Rodando server'))

Aqui temos uma api simples onde usamos o express para facilitar a criação. Na rota "/number" é enviado por query os parâmetros numberOne e numberTwo, e a api retorna a multiplicação desses dois números. Esses numeros são enviados como string e passando esses parâmetros para dentro da função eval() ela retorna eles como sendo do tipo number. Legal não é mesmo? NÃO, não é nada legal!

Como explicamos antes, a função avalia a expressão enviada para ela e executa o que tivermos lá dentro. A seguir vamos ver uma requisição feita e a resposta recebida de acordo com o que em teoria deveria acontecer!

curl -s "http://localhost:3000/number?numberOne=3&numberTwo=5"
response number: 15

Funcionando perfeitamente! Mas agora vamos brincar um pouco e enviar uma função javascript como parametro no numberTwo

//Função enviada
require('fs').readdir(__dirname,(err, files)=>console.log(files))

Resultado:

curl -s "http://localhost:3000/number?numberOne=3&numberTwo=require('fs').readdir(__dirname,(err, files)=>console.log(files))"
response number: NaN

Como resultado, tivemos um NaN. Parece que não aconteceu nada demais, porém dentro do servidor nós teremos este resultado:

[ 'node_modules', 'package-lock.json', 'package.json', 'server.js' ]

Injetamos uma função javascript e a função eval executou o comando dentro do servidor.

Isso é bem ruim não é mesmo? Sim, mas vamos piorar ainda mais! Que tal passamos para um DoS total? Vamos lá?

Basta pegarmos o mesmo curl e enviarmos uma nova função para dentro do parâmetro numberTwo

//Função enviada
process.kill(process.pid)

resultado:

curl -s "http://localhost:3000/number?numberOne=3&numberTwo=process.kill(process.pid)"

assim que fizer essa requisição, você não vai receber nenhuma resposta, simplesmente por que a aplicação será encerrada na mesma hora!

COMO SE PROTEGER?

Nós chamamos de normalização todo processo de sanitização de conteúdos externos, retirando tudo o que não é necessário e garantindo que nossa aplicação fique mais segura.

Um exemplo simples de sanitização feita no código.

const express = require('express')

express().get('/number', async(req, res) => {
    const numberOne = parseInt(req.query.numberOne)
    const numberTwo = parseInt(req.query.numberTwo)

    const response = numberOne * numberTwo
    
    res.end(`response number: ${response}`)
})

.listen(3000, () => console.log('Rodando server'))

Apenas trocamos a função eval() por parseInt() e isso já trás uma segurança gigantesca. Caso tentamos novamente fazer a requisição, este será o resultado.

curl -s "http://localhost:3000/number?numberOne=3&numberTwo=process.kill(process.pid)"
response number: NaN

A resposta será um NaN por que a função parseInt vai tentar fazer a conversão da string e não vai conseguir. Vai retornar um erro, porém isso pode ser tratado e a aplicação pode seguir funcionando normalmente.

CONCLUSÃO

Vale lembrar que o express já da alguma ajuda para nós programadores, então, caso seja enviado algo por parâmetro, esse parâmetro será transformado em uma string, porém essa solução não é um bala de prata, nós programadores precisamos ter noções de segurança, para assim, conseguir garantir aplicações melhores para nós e para nossos usuários.

Desde já agradeço a sua presença nesse meu primeiro artigo, e até uma próxima.

Carregando publicação patrocinada...