( Редактировать Этот ответ относится к вашему вопросу перед редактированием. Не знаю ни одного скриптового языка, реализованного с использованием Javascript, хотя я ожидаю, что они есть. Например, однажды кто-то написал BASIC для Javascript (раньше имелась ссылка, но она сгнила). Поэтому остальная часть этого ответа довольно академична, но я оставил его только для обсуждения, иллюстрации и даже предостережения. Кроме того, я определенно согласен с bobince's очки - не делайте этого сами, используйте работу других, например Каха .)
Если вы разрешите какой-либо сценарий в пользовательском контенте, будьте готовы к тому, что вы попадете в гонку вооружений людей, которые находят дыры в ваших механизмах защиты и используют их, и вы реагируете на эти эксплойты. Я думаю, что, вероятно, уклонюсь от этого, но вы знаете свое сообщество и свои варианты борьбы со злоупотреблениями. Итак, если вы готовы к этому:
Из-за способа, которым Javascript выполняет разрешение символов, кажется, что должна быть возможность оценить скрипт в контексте, где window
, document
, ActiveXObject
, XMLHttpRequest
и тому подобное не имеют их обычные значения:
// Define the scoper
var Scoper = (function() {
var rv = {};
rv.scope = function(codeString) {
var window,
document,
ActiveXObject,
XMLHttpRequest,
alert,
setTimeout,
setInterval,
clearTimeout,
clearInterval,
Function,
arguments;
// etc., etc., etc.
// Just declaring `arguments` doesn't work (which makes
// sense, actually), but overwriting it does
arguments = undefined;
// Execute the code; still probably pretty unsafe!
eval(codeString);
};
return rv;;
})();
// Usage:
Scoper.scope(codeString);
(Теперь это использует зло eval
, но я не могу сразу придумать способ скрыть объекты по умолчанию через кросс-браузер без использования eval
, и если вы все равно получаете код в виде текста ... .)
Но это не работает , это только частичное решение (подробнее ниже). Логика заключается в том, что любая попытка в коде в codeString
получить доступ к window
(например) будет обращаться к локальной переменной window
, а не к глобальной; и то же самое для других. К сожалению, из-за способа разрешения символов к любому свойству window
можно получить доступ с префиксом window.
или без него (например, alert
), поэтому вы должны также перечислить их. Это может быть длинный список, не в последнюю очередь потому, что, как указывает bobince , IE сбрасывает любой элемент DOM с именем или идентификатором в window
. Таким образом, вам, вероятно, придется поместить все это в свой собственный iframe, чтобы вы могли выполнить окончательный анализ проблемы , которая , и «только» приходится иметь дело со стандартными вещами. Также обратите внимание, как я сделал функцию scope
свойством объекта, а затем вы только вызываете ее через свойство. Это так, что this
установлен на экземпляр Scoper
(в противном случае при вызове необработанной функции this
по умолчанию равен window
!).
Но, как указывает Бобинс, есть так много разных способов добраться до вещей. Например, этот код в codeString
успешно ломает тюрьму выше:
(new ('hello'.constructor.constructor)('alert("hello from global");'))()
Теперь, возможно вы можете обновить джейл, чтобы этот конкретный эксплойт не работал (осматривая свойства constructor
для всех & mdash; all & mdash; встроенных в объектах), но я склонен сомневаться в этом. И если бы вы могли , кто-то (например, Боб) просто придумал бы новый эксплойт, такой как этот:
(function(){return this;})().alert("hello again from global!");
Отсюда и "гонка вооружений".
Единственный действительно тщательный способ сделать это состоит в том, чтобы встроить в ваш сайт правильный анализатор Javascript, проанализировать его код и проверить наличие недопустимого доступа, и только после этого запускать код. Это много работы, но если ваш сценарий использования оправдывает это ...