O que constitui "uso inadequado" do recurso javascript Eval? [fechadas]


13

Eval é um recurso de linguagem notoriamente controverso. Douglas Crockford rejeita. Estou imaginando quais riscos específicos o Eval traz. De acordo com esta pergunta Improper use of eval opens up your code for injection attacks,.

Quais são alguns usos impróprios do comando Eval e quais falhas de segurança eles abrem?

Respostas:


31

Quando eu estava implementando o mecanismo JScript, eu defendia a impressão de camisas EVAL IS EVIL , mas, infelizmente, nunca chegamos a isso.

Meu maior problema com a avaliação não é o óbvio ataque malicioso de injeção de código, embora isso certamente seja uma preocupação enorme. Meu maior problema é que as pessoas tendem a usá-lo como um martelo realmente grande para resolver problemas realmente pequenos. A maioria dos usos do mundo real que eu vi de "eval" na natureza quando eu estava na equipe do JScript poderia ter sido resolvida trivialmente usando uma tabela de pesquisa; e como todo objeto no JScript já é uma tabela de pesquisa , não é como se isso fosse um fardo oneroso. O Eval inicia o compilador novamente e destrói completamente a capacidade do compilador de otimizar seu código .

Para mais algumas reflexões nesse sentido, veja meus artigos de 2003 sobre o assunto:

Maldade geral:

http://blogs.msdn.com/b/ericlippert/archive/2003/11/01/53329.aspx

Ataque do ataque por injeção:

http://blogs.msdn.com/b/ericlippert/archive/2003/11/04/53335.aspx


O que você pensa sobre evalgrandes pedaços de código da maneira que aplicativos como o JSPacker gostam? O JSPacker + gzip geralmente resulta em tamanhos de arquivo menores do que qualquer solução por si só, mas como você corretamente aponta, ele essencialmente está disparando um compilador duas vezes no mesmo pedaço de código, além de algumas despesas gerais para fazer substituições de cadeias.
Matthew Scharley 22/03

2
@ Matthew: Muitas vezes há uma troca entre espaço e tempo, e tirar vantagem dessa troca pode às vezes ser uma grande vitória. Se o objetivo da técnica é melhorar o desempenho, minha opinião é que, se uma medição cuidadosa mostrar que é uma vitória significativa em cenários realistas sem introduzir falhas de segurança, ótimo, faça isso. Mas não sei o suficiente sobre a técnica específica para criticar seus detalhes.
22611 Eric Lippert

Desejo uma das respostas que eu tinha visto , quer aqui ou no SO em si teria dito o que seu segundo link estados: que eval()é não um risco de segurança em código de cliente (browser).
sq33G

4

A maioria das falhas de segurança é do mesmo tipo que na injeção SQL, concatenando a entrada do usuário no código JavaScript. A diferença é que, embora haja maneiras de garantir que isso não aconteça com o SQL, não há muito o que fazer com JavaScript.

Como um exemplo trivial e inútil, uma calculadora JavaScript simplista:

textbox1.value = eval(textbox2.value);

Um exemplo de uso correto são alguns dos empacotadores JavaScript que compactam o JavaScript, retirando palavras comuns e substituindo-as por substituições curtas de 1-2 caracteres. O empacotador gera tudo isso junto com o código de substituição de string com base no dicionário gerado e avalia o resultado.


1

Há algumas coisas que são impossíveis de fazer em JS sem uma função eval-like ( eval, Functione talvez mais).

Tome applypor exemplo. É fácil de usar ao usá-lo em chamadas de funções comuns:

foo.apply(null, [a, b, c])

Mas como você faria isso para objetos que você está criando através de nova sintaxe?

new Foo.apply(null, [a, b, c]) não funciona, nem formas semelhantes.

Mas você pode contornar essa limitação via evalou Function(eu uso Functionneste exemplo):

Function.prototype.New = (function () {
    var fs = [];
    return function () {
        var f = fs[arguments.length];
        if (f) {
            return f.apply(this, arguments);
        }
        var argStrs = [];
        for (var i = 0; i < arguments.length; ++i) {
            argStrs.push("a[" + i + "]");
        }
        f = new Function("var a=arguments;return new this(" + argStrs.join() + ");");
        if (arguments.length < 100) {
            fs[arguments.length] = f;
        }
        return f.apply(this, arguments);
    };
}) ();

Exemplo:

Foo.New.apply(null, [a, b, c]);

Obviamente, você pode criar manualmente as funções que Function.prototype.Newusa, mas não apenas isso é detalhado e desajeitado, mas (por definição) precisa ser finito. Functionpermite que o código funcione para qualquer número de argumentos.


2
É verdade, mas a pergunta do OP foi " Quais são alguns usos indevidos do comando Eval, e que falhas de segurança que eles abrir? ", E não " O que é um bom uso de eval()? "
Ross Patterson

1
@ RossPatterson: Acho que eu olhei principalmente para o título da pergunta, haha.
Thomas Eding

Ainda assim, um para encontrar um bom uso para um recurso de linguagem ruim :-)
Ross Patterson

1

Uma resposta direta da minha parte foi o desenvolvimento de uma área de teste de API orientada ao desenvolvedor. Fornecemos uma área de texto em uma página e um botão Executar. O ponto central da página era que eles pudessem experimentar coisas em Javascript contra nossa API de comunicação de iframe que não era tão fácil de fazer em um ambiente local.

Qualquer coisa maliciosa que pudesse ter sido feita nesse caso também poderia ter sido feita pelo desenvolvedor abrindo suas ferramentas F12.


0

Concordo que raramente deve ser usado, mas encontrei um caso de uso poderoso para eval.

Há um novo recurso experimental no Firefox chamado asm.js com o qual estou trabalhando. Ele permite que um subconjunto limitado da linguagem Javascript seja compilado no código nativo. Sim, isso é muito impressionante, mas tem limitações. Você pode pensar no subconjunto limitado de Javascript como uma linguagem semelhante a C incorporada ao Javascript. Não é realmente para ser lido ou escrito por humanos.

Esse subconjunto limitado de Javascript não permite que eu injete meu código gerado em tempo de execução no código compilado depois de compilado.

Eu escrevi um código que permite ao usuário escrever, em notação familiar, uma expressão matemática e convertê-la rapidamente para o código asm.js. A menos que eu queira que o código seja processado no lado do servidor (o que não evalé o caso ), é a única ferramenta que me permite processar o código resultante pelo navegador em tempo real.


0

Conforme apontado por outros, a coisa mais importante quando se trabalha evalé mantê-lo seguro. Para isso, você deseja fazer uma verificação completa de argumentos e manter evalo código simples, pois geralmente é muito mais difícil manter e proteger o código gerado em tempo de execução.

Dito isto, gosto de usar evalpara dois tipos de coisas (mesmo que provavelmente haja alternativas melhores e menos malignas):

  1. Como evalé uma maneira de "colocar em cache explicitamente o código", ele pode ser usado para melhorar o desempenho. Observe que os otimizadores estão sempre sendo aprimorados, mas simplesmente não há garantia sobre o que eles podem fazer por você. Ao tornar as coisas explícitas no código, você realmente pode ajudar o otimizador a tomar decisões mais inteligentes.
  2. Também pode ser usado para fornecer formas básicas de segurança de tipo, bem como outros recursos de linguagem que o JS não possui, sem prejudicar o desempenho.

Essa abordagem do iterador de objetos pré-compilados , por exemplo, mostra benefícios claros de desempenho ao usar evalpara iteração de propriedades de objetos. Também mostra o início de um poderoso sistema de tipos que pode fornecer verificação implícita de restrições e muito mais, com pouco ou nenhum custo.

Muitos desenvolvedores experientes de Javascript provavelmente apontariam que essa é uma toca de coelho, pois, se você começar a escrever Javascript dessa maneira, alterará essencialmente a maneira como usa a linguagem. No entanto, isso pode não ser necessariamente algo ruim para quem gosta de Javascript, mas também está faltando recursos fundamentais da linguagem que só podem ser alcançados alterando a maneira como usamos a própria linguagem.


-3

Eu tenho uma situação em que eval se parece com o caminho a percorrer, avaliando uma string e retornando uma variável existente cujo nome é o mesmo da string.

Eu tenho várias tabelas: table1ResultsTable, table2ResultsTable, tableNResultsTable. Eu tenho variáveis ​​configuradas com os mesmos nomes, que são objetos de dados jQuery. Eu os uso para configurar as tabelas e chamar funções de dados do jQuery nelas.

Cada tabela possui class = "resultsTable" atribuído. Agora, preciso obter a variável quando a tabela é clicada. Eu estou fazendo isto:

$('resultsTable).on('click', 'td', function(event) {
    var cResultsTable = eval(event.target.parentElement.parentElement.parentElement.id);
    [etc]
});

Então, eu estou recebendo o ID da tabela na qual a célula foi clicada, que tem o mesmo nome que a variável de objeto de tabela de dados correspondente a ela. Se alguém tiver uma sugestão para uma melhoria, eu gostaria de saber sobre isso.


1
Por que você precisa de avaliação? O ID deve ser uma sequência simples, não um código. De qualquer forma, event.target.parentElement.parentElement.parentElementé horrível. Além disso, eu esperaria que a chamada eval gere um erro "erro de referência: [id] não está definido", a menos que você esteja usando deliberadamente IDs avaliáveis ​​(que estão quebrados, incorretos e podem causar coisas estranhas se você terminar gerar IDs duplicados).
Brian

Talvez eu não esteja me esclarecendo. A identificação é uma sequência simples. É o ID da tabela que foi clicada. Eu também tenho uma variável de objeto (definida com o método jQuery datatable (), referenciando a mesma tabela) com o mesmo nome que o id. Estou tentando obter essa variável, acessar suas funções (de fato, adicionar a classe "row_selected" à linha selecionada), quando a tabela é clicada. Desde que eu escrevi isso, eu tive uma melhora, no entanto. Eu apenas coloquei todas as referências de objetos em uma matriz, nomeie os elementos da mesma forma que o id e plugue a string de ID para obter o ref do objeto.
BobRodes

Brian, se você tem um meio melhor de encontrar o ID da tabela que foi clicada, sou todo ouvidos. Para a função de tabelas de dados, preciso manipular o evento click na célula e adicionar a classe row_selected ao seu parentNode. Por que não consigo lidar com o evento da linha e adicionar a classe diretamente a ele, não sei, mas a linha não aparece como selecionada quando faço isso.
BobRodes

1
Talvez eu não esteja me esclarecendo. Se você chamar eval em uma sequência simples (ou seja, não JS), lançará uma exceção. Portanto, seu uso de eval não faz sentido. Se você estiver gerando uma variável de objeto com o mesmo nome que o id, seu código funcionará ... mas me parece que está quebrado. Prefiro criar a variável usando document.getElementById(ID).MySpecialProperty = MYSPECIALPROPERTYVALUE(para não dizer que isso é ótimo também, mas é melhor que eval). Como Eric Lippert aponta, "todo objeto no JScript já é uma tabela de pesquisa".
18713 Brian

Ok, então você está dizendo para adicionar uma propriedade à referência do elemento e configurá-la para a referência do objeto de tabela de dados? Isso parece mais apertado para mim também.
precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.