Есть ли способ заключить в тюрьму в Javascript, чтобы DOM не был виден - PullRequest
9 голосов
/ 20 апреля 2010

Я действительно хотел бы предоставить пользователю некоторые возможности сценариев, не предоставляя ему доступа к более мощным функциям, таким как изменение DOM. То есть весь ввод / вывод проходит через данный интерфейс. Как своего рода ограниченный javacsript.

Пример: Если интерфейс checkanswer(func) это разрешено:

checkanswer( function (x,y)={
   return x+y;
}

но это не разрешено:
alert(1)
document.write("hello world")
eval("alert()")

РЕДАКТИРОВАТЬ: я имел в виду простой язык, который был реализован с использованием JavaScript, что-то вроде http://stevehanov.ca/blog/index.php?id=92

Ответы [ 7 ]

14 голосов
/ 20 апреля 2010

( Редактировать Этот ответ относится к вашему вопросу перед редактированием. Не знаю ни одного скриптового языка, реализованного с использованием 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, проанализировать его код и проверить наличие недопустимого доступа, и только после этого запускать код. Это много работы, но если ваш сценарий использования оправдывает это ...

5 голосов
/ 20 апреля 2010

T.J. Краудер замечательно говорит о «гонке вооружений». Это будет очень трудно построить водонепроницаемую песочницу.

однако некоторые функции можно переопределить довольно легко.

Простые функции:

И согласно этот вопрос , даже переопределяя такие вещи, как document.write, так же просто, как

document.write = function(str) {}

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

Альтернативные варианты:

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

  • Парсинг кода пользователя с использованием белого списка разрешенных функций. Ужасно сложно сделать это, потому что есть так много обозначений и вариантов, о которых нужно заботиться.

  • Существует несколько методов для отслеживания изменений в DOM, и я уверен, что можно создать механизм, который немедленно отменяет любые изменения, очень похожий на управление DLL в Windows. Но это будет очень сложно построить и очень ресурсоемко.

3 голосов
/ 20 апреля 2010

Не совсем. JavaScript - это чрезвычайно динамичный язык со множеством скрытых или специфичных для браузера функций, которые можно использовать для выхода из любой тюрьмы, которую вы можете создать.

Не пытайтесь взять это на себя. Рассмотрите возможность использования существующего проекта «mini-JS-like-language», такого как Caja .

0 голосов
/ 17 июля 2012

А как насчет этого шаблона для реализации песочницы?

function safe(code,args)
{
    if (!args)
        args=[];
    return (function(){
    for (i in window) 
        eval("var "+i+";");
    return function(){return eval(code);}.apply(0,args);
    })();
}



ff=function()
{
    return 3.14;
}

console.log(safe("this;"));//Number
console.log(safe("window;"));//undefined
console.log(safe("console;"));//undefined
console.log(safe("Math;"));//MathConstructor
console.log(safe("JSON;"));//JSON
console.log(safe("Element;"));//undefined
console.log(safe("document;"));//undefined
console.log(safe("Math.cos(arguments[0]);",[3.14]));//-0.9999987317275395
console.log(safe("arguments[0]();",[ff]));//3.14

Возвращает:

Number
undefined
undefined
MathConstructor
JSON
undefined
undefined
-0.9999987317275395
3.14 

Не могли бы вы предоставить эксплойт, подходящий для атаки на это решение? Просто чтобы понять и улучшить свои знания, конечно :)

СПАСИБО!

0 голосов
/ 23 апреля 2010

У меня есть другой способ: использовать Google Gears WorkerPool api
Посмотреть это
http://code.google.com/apis/gears/api_workerpool.html

Созданный работник не имеет доступа в DOM; объекты, такие как документ и Окно существует только на главной странице. Это следствие работников не разделение любого состояния выполнения. Тем не мение, работники имеют доступ ко всем Встроенные функции JavaScript. Наиболее Методы Gears также могут быть использованы, через глобальную переменную, которая автоматически определяется: google.gears.factory. (Одно исключение является отправителем файла LocalServer, который требует DOM.) Для других функциональность, созданные работники могут спросить главная страница для выполнения запросов.

0 голосов
/ 20 апреля 2010

Вы можете сделать это так же, как Facebook. Они предварительно обрабатывают все источники javascript, добавляя префикс ко всем именам, кроме их собственных API-оболочек.

0 голосов
/ 20 апреля 2010

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

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