Функция eval - это мощный и простой способ динамического генерирования кода, так каковы предостережения?
javascript
security
eval
Брайан Сингх
источник
источник
Ответы:
Неправильное использование eval открывает ваш код для инъекционных атак
Отладка может быть более сложной (без номеров строк и т. Д.)
eval'd код выполняется медленнее (нет возможности компилировать / кэшировать eval'd код)
Редактировать: Как @Jeff Walden указывает в комментариях, # 3 сегодня менее верен, чем это было в 2008 году. Однако, хотя может происходить некоторое кэширование скомпилированных скриптов, это будет ограничено только скриптами, которые eval-повторялись без модификации. Более вероятным сценарием является то, что вы оцениваете скрипты, которые каждый раз подвергались небольшим изменениям и поэтому не могли быть кэшированы. Давайте просто скажем, что НЕКОТОРЫЙ eval'd код выполняется медленнее.
источник
badHackerGuy'); doMaliciousThings();
и если вы берете мое имя пользователя, объединяете его в некоторый скрипт и оцениваете его в браузерах других людей, тогда я могу запустить любой javascript, который я хочу, на их машинах (например, заставить их добавить +1 к моим сообщениям, опубликовать свои данные на моем сервере и т. д.)debugger;
оператор в ваш исходный код. Это остановит выполнение вашей программы в этой строке. Затем после этого вы можете добавить точки отладки, как если бы это был просто другой файл JS.Eval не всегда зло. Есть моменты, когда это совершенно уместно.
Однако eval в настоящее время и исторически массово используется людьми, которые не знают, что делают. К сожалению, это включает людей, пишущих учебники JavaScript, и в некоторых случаях это может иметь последствия для безопасности - или, чаще, простые ошибки. Таким образом, чем больше мы можем сделать, чтобы поставить вопросительный знак над eval, тем лучше. Каждый раз, когда вы используете eval, вам нужно проверять, что вы делаете, потому что, скорее всего, вы могли бы сделать это лучше, безопаснее и чище.
Чтобы дать слишком типичный пример, установить цвет элемента с идентификатором, хранящимся в переменной 'potato':
Если бы авторы приведенного выше кода имели представление об основах работы объектов JavaScript, они бы поняли, что вместо литеральных точечных имен можно использовать квадратные скобки, устраняя необходимость в eval:
... который намного легче читать, а также менее глючит.
(Но тогда кто-то, кто / действительно / знал, что они делают, скажет:
что более надежно, чем хитрая старая уловка доступа к элементам DOM прямо из объекта документа.)
источник
JSON.parse()
вместоeval()
JSON?Я считаю, что это потому, что он может выполнять любую функцию JavaScript из строки. С его помощью людям проще внедрить в приложение мошеннический код.
источник
На ум приходят два момента:
Безопасность (но пока вы сами генерируете строку для оценки, это может быть проблемой)
Производительность: до тех пор, пока исполняемый код неизвестен, его нельзя оптимизировать. (о javascript и производительности, конечно же, презентации Стива Йегге )
источник
eval
а затем этот маленький фрагмент кода запускается в браузере пользователя BПередача пользовательского ввода в eval () представляет собой угрозу безопасности, но каждый вызов eval () создает новый экземпляр интерпретатора JavaScript. Это может быть ресурсным боровом.
источник
Как правило, это проблема, только если вы передаете пользовательский ввод eval.
источник
В основном, это намного сложнее поддерживать и отлаживать. Это как
goto
. Вы можете использовать его, но это усложняет поиск проблем и усложняет работу с людьми, которым может потребоваться внести изменения позже.источник
Следует иметь в виду, что вы часто можете использовать eval () для выполнения кода в иным образом ограниченной среде - сайты социальных сетей, которые блокируют определенные функции JavaScript, иногда можно обмануть, разбив их на блоки eval -
Так что, если вы хотите запустить какой-то код JavaScript, который иначе не мог бы быть разрешен ( Myspace , я смотрю на вас ...), тогда eval () может быть полезным трюком.
Тем не менее, по всем причинам, указанным выше, вы не должны использовать его для своего собственного кода, где у вас есть полный контроль - это просто не нужно, и лучше отойти на полку «хитрых хаков JavaScript».
источник
[]["con"+"struc"+"tor"]["con"+"struc"+"tor"]('al' + 'er' + 't(\'' + 'hi there!' + '\')')()
Если вы не разрешите eval () динамический контент (через cgi или input), он будет таким же безопасным и надежным, как и любой другой JavaScript на вашей странице.
источник
Наряду с остальными ответами, я не думаю, что у заявлений eval может быть продвинутая минимизация.
источник
Это возможный риск для безопасности, он имеет другую область исполнения и совершенно неэффективен, поскольку создает совершенно новую среду сценариев для выполнения кода. Смотрите здесь для получения дополнительной информации: eval .
Это довольно полезно, хотя и использование с модерацией может добавить много хорошей функциональности.
источник
Если вы не уверены на 100%, что оцениваемый код получен из надежного источника (обычно из вашего собственного приложения), то это верный способ подвергнуть вашу систему атаке межсайтового скриптинга.
источник
Я знаю, что это обсуждение старое, но мне действительно нравится этот подход от Google, и я хотел поделиться этим чувством с другими;)
Другое дело, что чем лучше Ты получаешь, тем больше Ты пытаешься понять и, в конце концов, Ты просто не веришь, что что-то хорошо или плохо, только потому, что кто-то так сказал :) Это очень вдохновляющее видео, которое помогло мне больше думать самостоятельно :) ХОРОШИЕ ПРАКТИКИ хороши, но не используйте их безрассудно :)
источник
Это не обязательно так плохо, если вы знаете, в каком контексте вы его используете.
Если ваше приложение использует
eval()
для создания объекта из некоторого JSON, который вернулся из XMLHttpRequest на ваш собственный сайт, созданный вашим доверенным кодом на стороне сервера, это, вероятно, не проблема.Ненадежный код JavaScript на стороне клиента в любом случае не может этого сделать. Если вещь, на которой вы выполняете
eval()
, поступила из разумного источника, у вас все хорошо.источник
Это значительно снижает ваш уровень уверенности в безопасности.
источник
Если вы хотите, чтобы пользователь вводил некоторые логические функции и оценивал И ИЛИ, тогда JavaScript-функция eval идеально подходит. Я могу принять две строки и
eval(uate) string1 === string2
т. Д.источник
Если вы заметили использование eval () в своем коде, помните мантру «eval () - зло».
Эта функция принимает произвольную строку и выполняет ее как код JavaScript. Когда рассматриваемый код известен заранее (не определяется во время выполнения), нет смысла использовать eval (). Если код генерируется динамически во время выполнения, часто есть лучший способ достичь цели без eval (). Например, просто использовать квадратную скобку для доступа к динамическим свойствам лучше и проще:
Использование
eval()
также имеет последствия для безопасности, потому что вы можете выполнять код (например, поступающий из сети), который был подделан. Это распространенный антипаттерн при работе с JSON-ответом на запрос Ajax. В этих случаях лучше использовать встроенные в браузер методы для анализа ответа JSON, чтобы убедиться в его безопасности и допустимости. Для браузеров, которые не поддерживаютJSON.parse()
изначально, вы можете использовать библиотеку из JSON.org.Также важно помнить, что передача строк в
setInterval()
,setTimeout()
иFunction()
конструктор, по большей части, похожа на использование,eval()
и поэтому ее следует избегать.За кулисами JavaScript все еще должен оценить и выполнить строку, которую вы передаете как программный код:
Использование нового конструктора Function () аналогично eval () и к нему следует подходить с осторожностью. Это может быть мощная конструкция, но часто используется неправильно. Если вам абсолютно необходимо использовать
eval()
, вы можете вместо этого рассмотреть возможность использования новой функции ().Есть небольшое потенциальное преимущество, потому что код, оцененный в new Function (), будет работать в локальной области функций, поэтому любые переменные, определенные с помощью var в оцениваемом коде, не станут автоматически глобальными.
Другой способ предотвратить автоматические глобальные переменные -
eval()
превратить вызов в непосредственную функцию.источник
Помимо возможных проблем безопасности, если вы выполняете пользовательский код, в большинстве случаев есть лучший способ, который не требует повторного анализа кода при каждом его выполнении. Анонимные функции или свойства объекта могут заменить большинство применений eval и намного безопаснее и быстрее.
источник
Это может стать более серьезной проблемой, так как браузеры следующего поколения выпускают некоторые разновидности JavaScript-компилятора. Код, выполняемый через Eval, может не работать так же хорошо, как и остальная часть вашего JavaScript на этих новых браузерах. Кто-то должен сделать некоторое профилирование.
источник
Это одна из хороших статей, рассказывающих об eval и о том, как он не является злом: http://www.nczonline.net/blog/2013/06/25/eval-isnt-evil-just-misunderstood/
источник
eval () очень мощный и может использоваться для выполнения оператора JS или оценки выражения. Но вопрос не в том, как использовать eval (), а в том, как злоумышленник влияет на строку, которую вы запускаете с помощью eval (). В конце вы будете использовать вредоносный код. С силой приходит большая ответственность. Так что используйте это с умом, если вы используете это. Это не сильно связано с функцией eval (), но эта статья содержит довольно хорошую информацию: http://blogs.popart.com/2009/07/javascript-injection-attacks/ Если вы ищете основы eval () смотрите здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
источник
Механизм JavaScript имеет ряд оптимизаций производительности, которые он выполняет на этапе компиляции. Некоторые из них сводятся к возможности по существу статически анализировать код в процессе его лексического анализа и заранее определять, где находятся все объявления переменных и функций, так что для разрешения идентификаторов во время выполнения требуется меньше усилий.
Но если Механизм находит в коде eval (..), он, по сути, должен предположить, что вся его осведомленность о местоположении идентификатора может быть недействительной, потому что он не может точно знать, в какой момент времени лексинг точно, какой код вы можете передать eval (..) изменить лексическую область или содержимое объекта, который вы можете передать, чтобы создать новую лексическую область, к которой следует обращаться.
Другими словами, в пессимистическом смысле большинство из тех оптимизаций, которые он сделал бы, бессмысленно, если присутствует eval (..), поэтому он просто не выполняет оптимизацию вообще.
Это все объясняет.
Ссылка :
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#eval
https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/ch2.md#performance
источник
Это не всегда плохая идея. Взять, к примеру, генерацию кода. Недавно я написал библиотеку под названием Hyperbars, которая ликвидирует разрыв между виртуальным домом и рулем . Это делается путем анализа шаблона руля и преобразования его в гиперсценарий, который впоследствии используется virtual-dom. Гиперскрипт сначала генерируется в виде строки, а перед возвращением
eval()
превращается в исполняемый код. Я нашелeval()
в этой конкретной ситуации полную противоположность зла.В основном из
К этому
Производительность
eval()
не является проблемой в такой ситуации, потому что вам нужно только один раз интерпретировать сгенерированную строку, а затем многократно использовать исполняемый вывод.Вы можете увидеть , как генерация кода было достигнуто , если вам интересно здесь .
источник
Я бы сказал, что это не имеет значения, если вы используете
eval()
в JavaScript, который запускается в браузерах. * (Предостережение)Все современные браузеры имеют консоль разработчика, где вы в любом случае можете выполнить произвольный javascript, и любой полуумный разработчик может взглянуть на ваш JS-источник и поместить все нужные ему кусочки в консоль разработчика, чтобы сделать то, что он хочет.
* Пока ваши конечные точки сервера имеют правильную проверку и санацию предоставленных пользователем значений, не должно иметь значения, что анализируется и обрабатывается в вашем клиентском JavaScript.
Если вы спросите, подходит ли оно для использования
eval()
в PHP, ответ будет НЕТ , если только вы не внесете в белый список какие-либо значения, которые могут быть переданы в ваш оператор eval.источник
Я не буду пытаться опровергнуть все, что было сказано ранее, но я предложу использовать eval (), который (насколько я знаю) не может быть реализован каким-либо другим способом. Вероятно, есть другие способы кодирования этого и, возможно, способы его оптимизации, но это делается от руки и без наворотов для ясности, чтобы проиллюстрировать использование eval, у которого действительно нет других альтернатив. То есть: динамические (или точнее) программно созданные имена объектов (в отличие от значений).
РЕДАКТИРОВАТЬ: кстати, я бы не советовал (по всем причинам безопасности, указанным ранее), чтобы вы основали свои имена объектов на вводе пользователем. Я не могу представить себе вескую причину, по которой вы захотите это сделать. Тем не менее, я хотел бы указать, что это не будет хорошей идеей :)
источник
namespaceToTest[namespaceParts[i]]
, нет необходимости в Eval здесь, так чтоif(typeof namespaceToTest[namespaceParts[i]] === 'undefined') { namespaceToTest[namespaceParts[i]] = {};
единственная разница дляelse namespaceToTest = namespaceToTest[namespaceParts[i]];
Вывоз мусора
Сборщик мусора в браузерах не имеет представления, можно ли удалить код из eval'а из памяти, поэтому он просто сохраняет его до перезагрузки страницы. Неплохо, если ваши пользователи скоро появятся на вашей странице, но это может стать проблемой для веб-приложений.
Вот скрипт для демонстрации проблемы
https://jsfiddle.net/CynderRnAsh/qux1osnw/
Что-то такое простое, как приведенный выше код, приводит к тому, что небольшой объем памяти сохраняется до тех пор, пока приложение не умрет. Это хуже, когда уклоненный скрипт является гигантской функцией и вызывается через интервал.
источник