Руководство по безопасности браузеров (Browser Security Handbook). Глава 1
8. Браузерный Javascript
JavaScript - относительно простой, но богатый прототипно-ориентированный сценарный язык программирования, тесно интегрированный с HTML и поддерживаемый всеми современными браузерами. Название «JavaScript» - это просто маркетинговый ход, придуманный Netscape и Sun в 90-е годы. Авторы утверждают, что JavaScript берет свое начало от языков программирования Scheme и Self , хотя его часто характеризуют как скрещенный C/C++ и Visual Basic . Помимо схожести с Cи, он перенял некоторые функции языка Java .
Язык является детищем компании Netscape. Первоначально на рынке он был известен под именем «Mocha», затем «Livescript», и, наконец, «JavaScript»; Microsoft выпустила аналог языка JavaScript, названный JScript. По инициативе компании Netscape была проведена стандартизация языка ассоциацией ECMA. Стандартизированная версия имеет название ECMAScript и описывается стандартом ECMA-262 .
Браузерный JavaScript может быть вызван из HTML-документов четырьмя основными способами:
1. Автономным тегом <script>, расположенным в блоке кода.
2. Обработчиком событий, привязанным к тегам (например, onmouseover="...").
3. Блоком таблицы стилей expression(...) в некоторых браузерах, которые пропускают JavaScript-синтаксис.
4. Специальными URL-протоколами, указанными в качестве цели для определенных ресурсов или действия (javascript:...) - в HTML и таблицах стилей.
Обратите внимание на то, что первый вариант может не работать, если такая строка к существующему документу добавлена рабочим сценарием не динамически. Однако любой из оставшихся способов может использоваться в качестве альтернативы.
Независимо от их источника (<script src ="...">), удаленные скрипты всегда выполняются в контексте безопасности документа, к которому они прикреплены. JavaScript имеет полный доступ к текущему DOM, а также ограниченный доступ к DOM других окон; это может вызвать новые JavaScript путем вызова eval(), настройки таймера (setTimeout(...)и setInterval(...)), или путем создания JavaScript, используя HTML. JavaScript может также запуститься при взаимодействии его объектов со сторонним JavaScript-кодом сценария, настраивая часы, сеттеры (мутаторы) или геттеры (получатели) , или пересекающийся контекст, вызывая функции того же источника, принадлежащие другим документам.
JavaScriptимеет очень ограниченные возможности загрузки и вывода. Существует не так много доступных средств ввода-вывода для взаимодействия с данными документа и графикой CANVASec , отображения всплывающих диалоговых окон и записи консольных ошибок сценария. Операции с файлами и доступ к другому постоянному хранению, как правило, не возможны, несмотря на то, что некоторые экспериментальные функции вводятся и быстро отбраковываются. Сценарии могут отправлять и получать данные с исходного сервера, используя расширение XMLHttpRequest
Другими важнейшими характеристиками безопасности среды JavaScript в современных браузерах являются:
- Динамическая интерпретация исполняемого кода без строгих правил кэширования.Любые фрагменты кода, содержащиеся в тегах, будут интерпретированы и исполнены, и JavaScript имеет возможность оценить строки как JavaScript-код (eval (...)), или создать новый HTML, который, в свою очередь, может содержать другие сценарии (свойства .innerHTML и .outerHTML, document.write(), обработчики событий). Поведение кода, которое пытается изменить собственный контейнер во время выполнения (через DOM), определено нечетко и в разных браузерах отличается.
- Несколько противоречивая поддержка исключений. Несмотря на то, что в самом языке, условия для исключений хорошо определены, при взаимодействии с DOM-структурой это не работает. В зависимости от обстоятельств, некоторые операции с DOM могут не выполняться (игнорируется команда редактирования или чтения), возвращаться необычные ответы (undefined, null, object inaccessible), выдаваться нестандартизированные исключения, или даже безоговорочно прерываться выполнение.
- Несколько противоречивые, но модифицируемые встроенные команды и прототипы. Поведение многих языковых конструкций может быть переопределено программами в текущем контексте путем изменения объектов (сеттеров, геттеров) или перезаписью прототипов. Из-за этого рискованно полагаться на какой-либо конкретный код (например, проверку безопасности), выполняющийся предсказуемым способом в непосредственной близости от потенциально вредоносной полезной нагрузки. Однако не все встроенные объекты могут быть легко подделаны, например, Array - прототип сеттеров - может изменяться, но не так как XML. В JavaScript 1.x есть все необходимые для жизни операторы, хотя нет их перегрузки .
- Обычное синхронное выполнение. В пределах одного документа, на стороне браузера JavaScript обычно выполняется синхронно и в едином потоке, и асинхронным событиям таймера не разрешается запускаться до тех пор, пока механизм выполнения сценариев не введет состояние ожидания. Не существует никаких гарантий синхронного выполнения, однако, многопроцессорный рендеринг Chrome и MSIE8 позволяет осуществлять междоменный доступ более асинхронно.
- Глобальные функциональные поиски не зависят от упорядочивания или потока выполнения.Функции могут быть вызваны в блоке кода прежде, чем они будут определены и проиндексированы. Поэтому доверять операторам, таким, как while (1);для предотвращения последующего интерпретированного кода, может быть рискованно.
- Бесконечные циклы, которые завершаются. Когда сценарий выполняется слишком долго, пользователю предлагают прервать выполнение. Это способ защиты заставляет остановить текущее выполнение, но не препятствует его повторному запуску.
- Быстро развивающийся синтаксис. Например, в Firefoxрасширение языка программирование « ECMAScript for XML (E4X) » добавляет встроенную поддержку XML в JavaScript . Трудно представить, что какой-то формат данных будет не допустим JavaScript-синтаксисом в будущем.
Встроенные в HTML блоки сценария, сложнее удалить, если разрешено содержать управляемые пользователями строки, потому что, такие теги как <TEXTAREA>, <STYLE>и некоторые другие теги, идут за нелогичным анализом CDATA-style: последовательность литерала </SCRIPT> заканчивает блоком сценария независимо от своего расположения в синтаксисе JavaScript. Например, следующий блок кода завершится преждевременно и приведет к несанкционированному, дополнительному выполнению JavaScript-блока:
<SCRIPT> |
Грубо говоря, стандарт HTML4 определяет, что любая</...последовательность, (такая, как <SCRIPT>) может быть использована для высвобождения из блока . На практике, браузеры этому примеру не следуют и взамен требуют строку с литералом </SCRIPT>. Однако, на эту способность полагаться не безопасно.
Некоторые отличительные особенности браузеров приведены в таблице№10:
Таблица№10
Описание теста | MSIE7 | MSIE8 | FF3 | Safari | Opera | Chrome | Android |
Поддерживаются ли в настоящее время сеттеры и геттеры? | НЕТ | НЕТ | ДА | ДА | ДА | ДА | ДА |
Возможен ли доступ к прототипам через __proto__? | НЕТ | НЕТ | ДА | ДА | НЕТ | ДА | ДА |
Возможен ли псевдоним функции eval()? | ДА | ДА | ЧАСТИЧНО | ДА | ЧАСТИЧНО | ДА | ДА |
Поддерживается ли объектами метод watch? | НЕТ | НЕТ | ДА | НЕТ | НЕТ | НЕТ | НЕТ |
Могут ли в настоящем времени исполняемые блоки кода самостоятельно измениться? | только для чтения | только для чтения | НЕТ | НЕТ | ДА | НЕТ | НЕТ |
Поддерживается ли E4X-расширение? | НЕТ | НЕТ | ДА | НЕТ | НЕТ | НЕТ | НЕТ |
charset=соблюдается в <SCRIPTSRC="...">? (Ischarset=honoredon<SCRIPTSRC="...">?) | ДА | ДА | ДА | ДА | НЕТ | ДА | ДА |
Unicode-символы новой строки (U+2028, U+2029) разбивают строки в Javascript? | НЕТ | НЕТ | ДА | ДА | ДА | ДА | ДА |
Общая информация: программы на Javascriptмогут инициировать или перехватывать различные элементы (такие как мышь и клавиатуру) в пределах окна. Это может нарушить работу других механизмов защиты, таких как "защищенное" поле <INPUT TYPE=FILE ...>или HTML-фреймы с другого источника. Во время проектирования этим взаимодействиям было уделено недостаточно внимания, что привело к проблемам реализации в современных браузерах.
Кодировка символов в Javascript
Для обработки строк, содержащих строковые литералы, такие как </SCRIPT>, ", ', CLили LF идругие непечатаемые символы, JavaScript предлагает пять схем кодирования символов:
1. 8-разрядное восьмеричное числовое представление, содержащее три цифры, дополненное нулем, Си-стиль (C-style) ("test"
1. 8-разрядное восьмеричное числовое представление, содержащее три цифры, дополненное нулем, Си-стиль (C-style) ("test"
Ваша приватность умирает красиво, но мы можем спасти её.