Использовать eval без угрозы XSS

#javascript #security #xss #eval

#javascript #Безопасность #xss #eval

Вопрос:

Я создавал (не сейчас, но все еще мне это интересно) игру, использующую HTML5 и JS, и я хотел, чтобы люди могли вставлять пользовательский скрипт, но безопасно.

 function executeCustomJS(code){
 eval(code);//bad
}
  

Конечно, этот код очень плох, потому что если код будет чем-то вроде document.location.href='http://meatspn.com' , то результат станет очень …(…)

Одно из решений, которое я нашел, заключается в экранировании (например, eval -> ___eval___ ) всех ключевых слов и исключении ключевых слов из белого списка, таких как ‘while’, ‘for’, ‘if’, ‘var’, ‘true’, ‘false’, … и ‘func0’, ‘func1’, …., которые являются чем-то вроде API) игры и безопасны.

Например,

 function executeCustomJS(code){
 code = code.replace(/(Keyword RegEx)/g,'___$1___');
 /*unescape keywords in whitelist*/
 eval(code);
}
  

Я не вводил регулярные выражения и прочее в комментарии, но вопрос не в этом.

Давайте предположим, что строки в коде не экранируются, нет функции, которую можно создать путем экранирования строки, а ‘eval’, ‘window’, ‘document’, ‘alert’, ‘location’ отсутствуют в белом списке. Тем не менее, некоторые люди могут выполнять код, подобный while(true){} , они не могут выполнить какой-либо код, подобный document.location.href='http://meatspn.com' .

Безопасен ли этот метод? Или, существует ли лучший способ или нет?

Ответ №1:

Я рекомендую вам использовать ограниченный язык сценариев поверх JSON. Итак, задокументируйте механизм сценариев, который требует от вас создания объекта JSON в качестве вашего кода.

Это имеет большое преимущество в том, что в JSON невозможно внедрить неправильный код, потому что это просто данные.

Таким образом, вы можете создать какой-то декларативный синтаксис для вашего скриптового кода. Например

 {
    "0": {
        "Action": "move",
        "X": 10,
        "Y": -5
    },
    "1": {
        "Action": "emote",
        "type": "dance"
    }
}
  

Теперь, что такое хороший дизайн для крошечного декларативного языка сценариев — это совершенно другой вопрос.

Комментарии:

1. Если предполагается, что это JSON, вам нужно обрабатывать имена свойств как строки. { "Action": ...

2. Спасибо! (но мне все еще интересно, безопасен ли мой метод ..)

3. @tylermwashburn на самом деле это объектный литерал. Но да, JSON нужны свойства в строках. @JiminP это безопасно, только если вы знаете о javascript больше меня ;). Я вижу ваш анализатор белого списка, вы отправили его мне. Я могу найти в нем все дыры. Вы собираетесь смотреть meatspn снова и снова 🙂

4. @Raynos С помощью объектного литерала вы все равно можете хранить больше данных. x: function () { bombJapan(); }

5. @tylermwashburn это правда. Но вы не можете создать объектный литерал, содержащий функцию через JSON.parse . Идея состоит в том, чтобы загрузить JSON, примером просто оказался объектный литерал, ограниченный JSON. Может быть, мне следует изменить пример на JSON 🙂

Ответ №2:

Предоставьте все, что пользователь может пожелать сделать как combinators , например, подъязык.

Ответ №3:

https://developers.google.com/caja/

Компилятор Caja — это инструмент для обеспечения безопасности встраивания сторонних HTML, CSS и JavaScript на ваш веб-сайт. Это обеспечивает эффективное взаимодействие между страницей встраивания и встроенными приложениями. Caja использует объектно-ориентированную модель безопасности, обеспечивающую широкий спектр гибких политик безопасности, чтобы ваш веб-сайт мог эффективно контролировать, что встроенный сторонний код может делать с пользовательскими данными.