Лошо ли е това използване на eval() на Javascript?

Прочетох няколко неща относно eval на Javascript, така че мисля, че използването ми има смисъл.

Аз съм в клас по информационна сигурност и правим статистически анализ на лотарийни карти. Въпреки това, нашите са бинго карти (и вероятно е напълно малко вероятно да бъдат жертва на тази конкретна ситуация). Текущият ни процес обаче е с много грешки, така че имах идеята да съхранявам данните от картата на моя сървър и да позволя на съучениците да пишат функции на javascript в текстово поле и след това да натиснат бутон, който просто ще eval(textarea.value). Това ще ни позволи да направим някои доста полезни изчисления върху данните без много проблеми. Също така имах идеята за "съхраняване на процедури" като текст, който те могат да заредят в текстовото поле и след това да оценят.

Това лоша зона ли е за eval()? Или донякъде сива зона? Също така, какви са някои от потенциалните проблеми, с които мога да се сблъскам? Очевидно те биха могли потенциално да попречат на изгледа им на страницата, но стига да не правя нищо глупаво, обикновено презареждане на страницата трябва да поправи това, нали?

Благодаря!


person Wayne Werner    schedule 10.03.2011    source източник


Отговори (3)


Ако въвеждането на потребителя, което е eval()'d, винаги идва от потребителя, това трябва да е добре, единственият злонамерен JavaScript, който могат да изпълнят след това, е върху самите тях (което така или иначе биха могли да направят).

Ако говори с код от страна на сървъра, уверете се, че е валидиран като всеки друг външен вход.

Трябва също така да се уверите, че не може да бъде предварително попълнен от нещо като GET param и т.н.

Актуализация

Ако изпълнявате само основна математика с променливи, можете да използвате регулярен израз, за ​​да сте сигурни, че стойността е чиста от неаритметика и след това да я eval().

Например вашите уравнения могат да имат заместители CARD1 и CARD2.

var textarea = document.getElementsByTagName('textarea')[0],
    placeholders = ['CARD1', 'CARD2'];

document.getElementsByTagName('button')[0].onclick = function() {

    var value = textarea.value;

    // Strip placeholders
    var placeholderStripped = value.replace(new RegExp(placeholders.join('|'), 'g'), '');

    var safe = placeholderStripped.match(/^[\d\+\-\/\*\(\)]+$/);

    if (safe == null) {

        alert('Not a valid equation');
        return;

    }

    for (var i = 0, placeholdersLength = placeholders.length; i < placeholdersLength; i++) {
        value = value.replace(new RegExp(placeholders[i], 'g'), document.getElementById(placeholders[i].toLowerCase()).value);
    }

    document.getElementById('result').innerHTML = eval(value);

}

jsFiddle.

  • Използвайте прости имена на контейнери и всички главни букви за удобство. Ако използвате по-сложни имена, може да се наложи да използвате функция за екраниране на регулярен израз, преди да ги join().
  • Разрешаваме номера 0-9, +, -, /, *, ( и ). В момента не позволяваме десетични знаци. Това може да се добави, ако е необходимо.
  • Когато най-накрая eval() входа, той трябва да съдържа само имена на заместители (които ще бъдат заменени) и основните аритметични знаци по-горе.
  • Кодът, публикуван по-горе, е силно зависим от контекста на jsFiddle. Разбира се, никога няма да позволите имената на заместители да бъдат произволни - направете ги такива, каквито трябва да бъдат.
person alex    schedule 10.03.2011

Не искам да бъда мелодраматичен, но това вероятно е една от най-лошите употреби на eval(), тъй като ще изпълнявате произволен, предоставен от потребителя JavaScript. Това би позволило на потребителя да изпълни код на вашия домейн, което би направило XSS атака абсурдно проста.

Редактиране: Като се замисля, може би съм твърде драматичен. Докато не поддържате тези функции и те просто се eval управляват на машината на клиента, тогава всъщност не позволявате нищо, което потребителят вече не може да направи в своята локална JavaScript конзола в браузъра. Просто се уверете, че не запазвате тези функции за други потребители, които да използват по-късно.

person Andrew Hare    schedule 10.03.2011
comment
Вероятно пропускам нещо, но разрешаването на eval() на textarea не е ли добре, стига кодът да не актуализира никакво състояние от страна на сървъра или да позволява да бъде предварително попълнен? Искам да кажа, добре поне от гледна точка на сигурността. - person alex; 10.03.2011
comment
@alex - Не, прав си. Предположих, че тези функции се запазват някъде за повторна употреба. - person Andrew Hare; 10.03.2011
comment
@Tomalak Geret'kal Да, разбира се, неговият случай на използване трябва да са потребители на JavaScript, които знаят какво правят :) - person alex; 10.03.2011
comment
@alex: хехе :) Успех с това, а! - person Lightness Races in Orbit; 10.03.2011
comment
Ако трябваше да запазя функциите (т.е. така че съучениците да споделят), разумно ли би било да попълня само текстовото поле, изисквайки от потребителя да щракне върху бутона за оценка? Разбира се, кодът, който се съхранява, ще бъде екраниран и т.н. - простото филтриране на всички появявания на предупреждение, скрипт, img и css от необработения текст ще бъде разумна защита или това все пак ще позволи XSS техники? - person Wayne Werner; 10.03.2011
comment
@Wayne Werner Не бихте могли безопасно да филтрирате лоши функции, главно защото JavaScript ще изпълни eval('a' + 'lert("whoops")'), което няма да бъде съпоставено от съвпадение на низ. - person alex; 10.03.2011
comment
Така че в този случай или изобщо не се съхраняват функции, или просто се разчита на лицето, което щраква върху бутона за оценка, за да може да погледне функцията и да каже ах да, нека не кликваме върху това? - person Wayne Werner; 10.03.2011
comment
@Wayne Werner: Всъщност можете да презапишете глобалните предупреждение, eval, XMLHttpRequest и т.н. Докато правите това, преди потребителският код да бъде оценен, това трябва да е (разумно) безопасно. Това, съчетано с това, че потребителят обръща внимание и не оценява нищо странно изглеждащо, трябва да е достатъчно за вашия случай на употреба. Очевидно бъдете много по-внимателни, ако планирате да направите нещо по-амбициозно (като публичен уебсайт). - person Pauan; 21.11.2012

От гледна точка на сигурността това е ОК, тъй като потребителят може да разбие само собствения си браузър... което не е нищо ново.

Въпреки това, от гледна точка на дизайна на GUI, това би се считало за разхвърляно. Ако потребителят може да предостави вход, който нарушава интерфейса и разбира се с пълен достъп до скриптове, те могат, тогава това се счита за грешка на интерфейса.

Въпреки това, вие не правите комерсиален продукт и изглежда, че това ще ви спести много усилия, така че просто бих го предпочел.

person Lightness Races in Orbit    schedule 10.03.2011