Javascript Eval özelliğinin “uygunsuz kullanımı” nı oluşturur? [kapalı]


13

Eval, tartışmalı bir dil özelliğidir. Douglas Crockford bunu reddetti. Eval'ın ne gibi riskler getirdiğini merak ediyorum. Bu soruya göre Improper use of eval opens up your code for injection attacks,.

Eval komutunun bazı uygunsuz kullanımları nelerdir ve hangi güvenlik açıklarını açarlar?

Yanıtlar:


31

JScript motorunu uygularken, EVAL IS EVIL gömleklerinin basılmasını savunmuştum ama ne yazık ki hiç uğraşmadık.

Eval ile ilgili en büyük sorunum kesinlikle kötü bir kod enjeksiyon saldırısı değil, bu kesinlikle büyük bir endişe. Benim en büyük sorunum, insanların gerçekten küçük problemleri çözmek için gerçekten büyük bir çekiç olarak kullanma eğiliminde olmaları. Ben JScript ekibindeyken vahşi doğada "eval" gördüğüm gerçek dünya kullanımlarının çoğu bir arama tablosu kullanılarak önemsiz bir şekilde çözülmüş olabilir; ve JScript'teki her nesne zaten bir arama tablosu olduğundan, bu külfetli bir yük gibi değil. Eval tekrar derleyici başlar ve tamamen kodunuzu optimize etmek derleyici yeteneğini yok eder .

Bu bağlamda daha fazla düşünce için 2003'teki konuyla ilgili makalelerime bakın:

Genel kötülük:

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

Enjeksiyon saldırısı kötülükleri:

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


evalBüyük kod parçalarını JSPacker gibi uygulamaların nasıl istediği hakkında düşünceleriniz nelerdir ? JSPacker + gzip genellikle her iki çözümden de daha küçük dosya boyutlarına neden olur, ancak haklı olarak işaret ettiğinizde, bir derleyiciyi aynı kod parçasına iki kez ateşler, ayrıca dize değiştirmeleri yapmak için bazı ek yükler çıkarır.
Matthew Scharley

2
@Matthew: Genellikle mekan ve zaman arasında bir ödünleşim vardır ve bu ödünleşmeden yararlanmak bazen büyük bir kazanç olabilir. Tekniğin amacı performansı artırmaksa, o zaman benim düşüncem, dikkatli bir ölçümün, güvenlik senaryoları getirmeden gerçekçi senaryolarda önemli bir kazanç olduğunu gösteriyorsa, bunu yapın. Ama detaylarını eleştirmek için belirli teknik hakkında yeterince bilgim yok.
Eric Lippert

Ben görmüştü cevapların bir dilek ya burada ya da benzeri kendisi ne ikinci bağlantı durumları ifade olurdu: o eval()olduğunu değil istemci (tarayıcı) kodunda bir güvenlik riski.
sq33G

4

Güvenlik deliklerinin çoğu, SQL enjeksiyonuyla aynı tür deliklerdir, yani kullanıcı girişini JavaScript koduna birleştirir. Aradaki fark, bunun SQL'de olmamasını sağlamanın yolları olsa da, JavaScript ile yapabileceğiniz çok şey yoktur.

Önemsiz ve işe yaramaz bir örnek olarak, basit bir JavaScript hesap makinesi:

textbox1.value = eval(textbox2.value);

Doğru kullanım örneklerinden biri, sık kullanılan kelimeleri çıkararak ve bunları kısa 1-2 karakterlik değiştirmelerle değiştirerek JavaScript'i sıkıştıran JavaScript paketleyicilerinden bazılarıdır. Daha sonra packer, üretilen sözlüğü temel alan dize değiştirme kodu ile birlikte tüm bunları çıktılar ve ardından sonucu değiştirir.


1

Bir eval benzeri fonksiyonu olmadan JS yapmak imkansız bazı şeyler vardır ( eval, Functionve belki daha fazla).

applyÖrneğin ele alalım. Sıradan işlev çağrılarında kullanırken kullanımı kolaydır:

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

Ancak, yeni sözdizimi ile oluşturduğunuz nesneler için bunu nasıl yaparsınız?

new Foo.apply(null, [a, b, c]) ne işe yaramaz ne de benzer biçimler.

Ancak bu kısıtlama üzerinde evalveya aracılığıyla çalışabilirsiniz Function( FunctionBu örnekte kullanıyorum):

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);
    };
}) ();

Misal:

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

Tabii ki, elle kullanılan işlevleri manuel olarak oluşturabilirsiniz Function.prototype.New, ancak sadece bu ayrıntılı ve hantal değil, (tanım gereği) sonlu olmak zorundadır. Functionkodun herhangi bir sayıda argüman için çalışmasına izin verir.


2
Doğru, ama OP'ın soru " bazı uygunsuz Eval komutunun kullanımları ve ne güvenlik delikleri açmak mı nelerdir? " Değil " iyi bir kullanım nedir eval()? "
Ross Patterson

1
@RossPatterson: Sanırım çoğunlukla sorunun başlığına baktım haha.
Thomas Eding

Yine de, kötü dil özelliği için iyi bir kullanım bulmak için +1 :-)
Ross Patterson

1

Benim açımdan biraz doğrudan bir cevap, geliştirici odaklı bir API test alanı geliştirmekti. Bir sayfada metin alanı ve Çalıştır düğmesi verdik. Sayfanın ana noktası, yerel bir ortamda yapılması kolay olmayan iframe iletişim API'mize karşı Javascript'te bir şeyler deneyebilmeleriydi.

Bu durumda yapılabilecek kötü amaçlı herhangi bir şey, geliştirici F12 araçlarını açarak da yapılabilirdi.


0

Çok nadiren kullanılması gerektiğine katılıyorum, ancak güçlü bir kullanım durumu buldum eval.

Firefox'ta üzerinde çalıştığım asm.js adında yeni bir deneysel özellik var. Javascript dilinin sınırlı bir alt kümesinin yerel koda derlenmesini sağlar. Evet, bu çok harika, ama sınırlamaları var. Javascript'in sınırlı alt kümesini Javascript'te gömülü C benzeri bir dil olarak düşünebilirsiniz. Gerçekten insanlar tarafından okunması veya yazılması amaçlanmamıştır.

Javascript'in bu sınırlı alt kümesi, çalışma zamanı tarafından oluşturulan kodumu derlendikten sonra derlenmiş koda enjekte etmeme izin vermiyor.

Ben bir kullanıcı, tanıdık gösterimde, matematiksel bir ifade yazmak ve asm.js kodu anında dönüştürülmüş sağlayan bazı kod yazdım. Kodun sunucu tarafında işlenmesini istemediğim sürece (ki ben değilim), evalortaya çıkan kodun tarayıcı tarafından gerçek zamanlı olarak işlenmesini sağlayan tek araçtır.


0

Başkaları tarafından belirtildiği gibi, çalışırken en önemli şey evalonu güvende tutmaktır. Bunun için kapsamlı bir argüman kontrolü yapmak ve eval'çalışma kodunu basit tutmak istersiniz, çünkü çalışma zamanı tarafından üretilen kodu korumak ve güvence altına almak genellikle çok daha zordur.

Bununla birlikte, evaliki tür şey için kullanmaktan zevk alıyorum (muhtemelen daha iyi, daha az şeytani alternatifler olsa da):

  1. Yana eval"açıkça kod önbelleğe" bir yoludur, performansını artırmak için kullanılabilir. Optimize edicilerin her zaman geliştirildiğini unutmayın, ancak sizin için neler yapabileceklerine dair hiçbir garanti yoktur. İşleri kodda açık hale getirerek, optimize edicinin daha akıllı kararlar almasına yardımcı olabilirsiniz.
  2. Ayrıca, performansı düşürmeksizin temel tip güvenliği ve JS'nin eksik olduğu diğer dil özelliklerini sunmak için de kullanılabilir.

Bu önceden derlenmiş nesne yineleyici yaklaşımı , örneğin, evalnesne özelliği yinelemesi için kullanıldığında net performans avantajları gösterir . Ayrıca, örtük kısıtlama kontrolü ve çok daha fazlasını, çok az maliyetle veya ücretsiz olarak sağlayan güçlü bir tür sisteminin başlangıcını gösterir.

Birçok tecrübeli Javascript geliştiricisi muhtemelen bir tavşan deliği olduğuna işaret eder, çünkü Javascript'i bu şekilde yazmaya başlarsanız, esas olarak dili kullanma şeklinizi değiştirirsiniz. Bununla birlikte, Javascript'ten hoşlananlar için ancak kötü bir şey olmayabilir, ancak aynı zamanda yalnızca dili kullanma şeklimizi değiştirerek elde edilebilecek temel dil özellikleri de eksik olabilir.


-3

Değerlendirme bir dize değerlendirmek ve adı dize ile aynı olan mevcut bir değişken döndürerek gitmek gibi görünüyor bir durum var.

Birkaç tablo var: table1ResultsTable, table2ResultsTable, tableNResultsTable. JQuery datatable nesneler olan aynı adlarla ayarlanmış değişkenler var. Bu tabloları ayarlamak ve jQuery datatable fonksiyonları onlara çağırmak için kullanın.

Her tabloya class = "resultsTable" atanır. Şimdi, tablo tıklandığında değişkeni almak gerekir. Bunu yapıyorum:

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

Yani hücrenin tıklandığı tablonun kimliğini alıyorum, buna karşılık gelen datatable nesne değişkeni ile aynı ada sahip. Birisi iyileştirme için bir öneri varsa, bunu bilmek istiyorum.


1
Neden eval'e ihtiyacınız var? Kimlik, kod değil düz bir dize olmalıdır. Her neyse, event.target.parentElement.parentElement.parentElementkorkunç. Ayrıca, kasten değerlendirilebilir kimlikleri (bozuk, yanlış ve sonlandırırsanız garip şeylerin oluşmasına neden olmuyorsanız), eval çağrısının "referans hatası: [id] tanımlanmadı" hatası oluşturmasını beklerim. yukarı yinelenen kimlikler oluşturma).
Brian

Belki de kendimi açıklığa kavuşturmuyorum. Kimlik düz bir dizedir. Tıklanan tablonun kimliği. Ayrıca bir nesne değişkeni (aynı tabloya referans veren jQuery datatable () yöntemi ile ayarlanır) id ile aynı ada sahip. Tablo tıklatıldığında, işlevlerini (aslında, "row_selected" sınıfı seçilen satıra eklemek için) erişmek için bu değişkeni almaya çalışıyorum. Bunu yazdığımdan beri bir gelişme buldum. Ben sadece bir dizi tüm nesne referansları koymak, öğeleri kimliği aynı ad ve ben nesne ref almak için içine kimlik dizesi takın.
BobRodes

Brian, tıklanan tablonun kimliğini bulmanın daha iyi bir yolu varsa, tamamen kulaklarım. Datatables işlevi için, hücreye karşı click olayı işlemek ve kendi parentNode için row_selected sınıfı eklemek gerekir. Neden sadece row olayını işleyemiyorum ve sınıfı doğrudan ona ekleyemiyorum, ama bunu yaptığımda satır seçili olarak gösterilmiyor.
BobRodes

1
Belki de kendimi açıklığa kavuşturmuyorum. Eval'i düz (ör. JS olmayan) bir dize olarak çağırırsanız, bir istisna atarsınız. Yani, eval kullanımınız mantıklı değil. Kimlikle aynı ada sahip bir nesne değişkeni oluşturuyorsanız, kodunuz işe yarayacaktır ... ancak bana bozuk olarak vuruyor. Değişkeni kullanarak kullanmayı tercih ederim document.getElementById(ID).MySpecialProperty = MYSPECIALPROPERTYVALUE(bunun da harika olduğunu söyleyemem, ancak eval'den daha iyidir). Eric Lippert'in belirttiği gibi, "JScript'teki her nesne zaten bir arama tablosudur."
Brian

Tamam, öyleyse eleman referansına bir özellik eklemeyi ve bunu datatable nesne referansına ayarlamayı mı söylüyorsunuz? Bana da daha sıkı geliyor.
BobRodes
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.