Возможна ли песочница JavaScript, запущенного в браузере? - PullRequest
132 голосов
/ 12 октября 2008

Мне интересно, можно ли выполнить изолированную программную среду JavaScript, работающую в браузере, чтобы предотвратить доступ к функциям, которые обычно доступны для кода JavaScript, выполняемого на HTML-странице.

Например, скажем, я хочу предоставить JavaScript API для конечных пользователей, чтобы они могли определять обработчики событий, которые будут запускаться, когда происходят "интересные события", но я не хочу, чтобы эти пользователи получали доступ к свойствам и функциям window объект. Могу ли я сделать это?

В простейшем случае, скажем, я хочу запретить пользователям звонить alert. Вот несколько подходов, о которых я могу подумать:

  • Переопределить window.alert во всем мире. Я не думаю, что это будет правильный подход, потому что другой код, выполняющийся на странице (то есть материал, не созданный пользователями в их обработчиках событий), возможно, захочет использовать alert.
  • Отправьте код обработчика событий на сервер для обработки. Я не уверен, что отправка кода на сервер для обработки является правильным подходом, потому что обработчики событий должны запускаться в контексте страницы.

Возможно, будет работать решение, в котором сервер обрабатывает пользовательскую функцию и затем генерирует обратный вызов для выполнения на клиенте? Даже если этот подход работает, есть ли лучшие способы решить эту проблему?

Ответы [ 13 ]

0 голосов
/ 12 октября 2008

1) Предположим, у вас есть код для выполнения:

var sCode = "alert(document)";

Теперь предположим, что вы хотите выполнить его в песочнице:

new Function("window", "with(window){" + sCode + "}")({});

Эти две строки при выполнении завершатся ошибкой, потому что функция «alert» недоступна из «песочницы»

2) И теперь вы хотите выставить элемент объекта окна с вашей функциональностью:

new Function("window", "with(window){" + sCode + "}")({
    'alert':function(sString){document.title = sString}
});

Действительно, вы можете добавить кавычки, избегая и сделать другую полировку, но я думаю, идея ясна.

0 голосов
/ 12 октября 2008

Откуда этот пользовательский JavaScript?

Вы мало что можете сделать, чтобы пользователь вставил код на вашу страницу и затем вызвал его из своего браузера (см. Greasemonkey, http://www.greasespot.net/). Это просто то, что делают браузеры.

Однако, если вы храните скрипт в базе данных, затем извлекаете его и выполняете eval (), вы можете очистить скрипт до его запуска.

Примеры кода, который удаляет все окна. и документ. Ссылки:

 eval(
  unsafeUserScript
    .replace(/\/\/.+\n|\/\*.*\*\/, '') // Clear all comments
    .replace(/\s(window|document)\s*[\;\)\.]/, '') // removes window. or window; or window)
 )

Это пытается предотвратить выполнение (не проверено) следующего:

window.location = 'http://mydomain.com';
var w = window  ;

Существует множество ограничений, которые вы должны применить к небезопасному пользовательскому сценарию. К сожалению, для JavaScript нет «контейнера для песочницы».

0 голосов
/ 12 октября 2008

Вы можете заключить код пользователя в функцию, которая переопределяет запрещенные объекты в качестве параметров - тогда они будут undefined при вызове:

(function (alert) {

alert ("uh oh!"); // User code

}) ();

Конечно, умные злоумышленники могут обойти это, проверив DOM Javascript и найдя не переопределенный объект, который содержит ссылку на окно.


Другая идея заключается в сканировании кода пользователя с помощью такого инструмента, как jslint . Убедитесь, что он не имеет предустановленных переменных (или: только те переменные, которые вы хотите), а затем, если какие-либо глобальные переменные установлены или доступны, не позволяйте использовать скрипт пользователя. Опять же, они могут быть уязвимы для обхода DOM - объекты, которые пользователь может построить с использованием литералов, могут иметь неявные ссылки на объект окна, к которым можно получить доступ, чтобы избежать песочницы.

...