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, которое позволяет сценариям передавать и читать произвольные полезные нагрузки; могут также автоматически отправлять запросы и считывать правильно отформатированные ответы на выдачу <script src ="..."> или <link rel ="stylesheet" href="..."> даже между доменами. Наконец, JavaScript может отправлять информацию на сторонние серверы, порождая такие объекты, как <img>, <iframe>, <object>, <applet>, или перенаправлять на другую страницу и одновременно автоматически кодировать информацию в URL, - но сценарий не может читать возвращаемые данные. Некоторые побочные каналы связанны с механизмами кэширования браузера и проверки безопасности DOM обеспечивают дополнительные побочные каналы между взаимодействующими сторонами.
Другими важнейшими характеристиками безопасности среды 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>
var user_string = 'Hello world</SCRIPT><SCRIPT>alert(1)</SCRIPT>';
</SCRIPT>
|
Грубо говоря,
стандарт HTML4 определяет, что любая </...
последовательность, (такая, как <SCRIPT>)
может быть использована для высвобождения
из блока. На практике, браузеры этому примеру не следуют и взамен требуют
строку с литералом </SCRIPT>. Однако, на эту
способность полагаться не безопасно.
Некоторые отличительные
особенности браузеров приведены в таблице№10:
Таблица№10
2. 8-разрядное шестнадцатеричное числовое представление, содержащее две цифры, дополненное нулем, C-style с префиксом \х ("test" → "t\x65st"),
3. 16-разрядное шестнадцатеричное числовое Unicode-представление, содержащее четыре цифры, дополненное нулем, с префиксом \u ("test" → "t\u0065st"),
4. префикс \ перед литералом ("test" → "t\est"),
5. Специальное сокращенное обозначение Cи-стиля
\ для некоторых управляющих символов (таких как
\n или
\t).
Четвертая схема является наиболее компактной, хотя и подвержена ошибкам; например, неспособность избежать
\ как
\\ может привести к строке
\" + alert(1);" преобразованной из
\\" + alert(1), и будет неправильно интерпретирована; это также частично пересекается с оставшимся
\-префиксом выходом из метода, и не совместима с синтаксисом языка C.
Анализ этих схем универсален для всех браузеров, когда введено меньшее количество цифр, чем требуется: значение интерпретируется правильно, и никакой последующий текст не используется (
"\1test" принят, и становится
"\001test").
Кодирование HTML-объектов не имеют особого значения внутри блоков
<SCRIPT>.
Забавно, несмотря на то, что все четыре вышеупомянутых схемы поддерживаются в JavaScript, предлагаемый информационный стандарт для представления объектов JavaScript (
JSON) и транспортно-ориентированная схема сериализации для объектов и массивов JavaScript (
RFC 4627) технически допускают только \u запись и, по-видимому, произвольное подмножество \ сокращенных кодов управляющего символа (варианты 3 и 5 в списке схем кодирования символов). Поскольку формат JSON является подмножеством синтаксиса языка JavaScript, то он может быть быстро десериализован встроенной функцией eval(). Кроме того, возможна вставка вполне работоспособных JavaScript-функций. Однако, из-за рекомендаций, приведенных в документе RFC, некоторое несвойственное выполнение parseJSON может неправильно обрабатывать обычные \х управляющие символы. Также не определено, по какой схеме будут следовать браузеры. В настоящее время рассмотрены
собственные, не исполняющие анализаторы предложенные для повышения производительности и безопасности.
В отличие от некоторых реализаций C, в JavaScript отдельные многострочные строковые литералы не разрешены, но отдельный \ в конце строки, может быть использован для разбиения длинных строк.