Я решился взяться за перевод проекта Михаила Залевски (Michal Zalewski) «
Browser Security Handbook»,
в котором описаны подходы к обеспечению безопасности в браузерах. Материал будет
полезен всем, кто интересуется веб-безопасностью.
Данная тема для меня нова, поэтому с переводом могут быть косяки. Текст
перевожу не слово в слово, основные моменты стараюсь изложить в более понятной для
российского восприятия форме. Привожу дополнительные ссылки, чтобы материал
могли освоить такие же, как я, т.е. пользователи с минимальными знаниями в
данной сфере. Также прошу у читателей помощи в переводе; готов выслушать любую
критику по тексту.
Руководство по безопасности
браузеров
(Browser Security Handbook)
Глава 1
Веб-браузер. Основные понятия
В этом разделе дается обзор основных стандартов и технологий,
используемых в современных браузерах и их защитных свойств.
1. Унифицированный указатель ресурса (URL)
Все веб-ресурсы
адресуются с использованием унифицированного указателя ресурса. Возможность
должным образом анализировать форму и содержащихся в ней допустимых данных
является для многих серверных механизмов безопасности важным критерием.
Абстрактный
синтаксис[1] для URI описан в
RFC-3986.
Данный документ определяет основную иерархическую URI-структуру, рекомендательный
список «незарезервированные символы», которые отображаются в URI как есть (0-9 A-Z a-z - . _ ~), спецсимволы,
имеющие определенное функциональное назначение (: / ? # [ ] @ ! $ & ' ( ) *
+ , ; =), а также, записанные в
шестнадцатеричном
представлении с использованием знака «%» (%nn)[2], все остальные символы (в
том числе и сам знак «%»).
<схема>://<логин>:<пароль>@<хост>:<порт>/<URL-путь>?<параметры>#<якорь>
где,
схема - схема обращения к ресурсу
(в большинстве случаев имеется в виду сетевой протокол);
логин - имя пользователя, используемое
для доступа к ресурсу;
пароль - пароль указанного пользователя;
хост - полностью прописанное доменное
имя хоста в системе DNS или IP-адрес хоста в форме четырёх групп десятичных
чисел, разделённых точками;
порт - порт хоста для подключения;
URL-путь - уточняющая информация о
месте нахождения ресурса;
параметры - строка запроса с
передаваемыми на сервер (методом GET) параметрами. Разделитель
параметров — знак «&». Пример записи параметров:
?параметр_1=значение_1&параметр_2=значение_2&параметр3=значение_3
якорь - идентификатор «якоря»,
ссылающегося на некоторую часть (раздел) открываемого документа.
Помимо
вышеуказанных документов, «стандарты»
RFC1630 и
RFC2368 описывают в общих чертах некоторые дополнительные понятия, такие как «строгий
синтаксис строки поиска HTTP» (параметр_1=значение_1[&параметр_2=значение_2&...]),
или возможность использовать знак «+» как сокращенное обозначение пробела (сам символ
не используется по назначению в URL, что несколько необычно).
Несмотря на
то, что многие спецсимволы заданы в качестве разделителей в общем URL-синтаксисе,
только части из них отводится четкая роль в HTTP-адресе; функции для символов [, ],
!, $, ', (, ),
*, ;, или , явно нигде не
определены, но они иногда используются как инструмент для скрытной передачи
параметров в структуру web-приложений.
Сам RFC иногда
подразумевает, что символы без конкретных функций в схеме должны быть обработаны
как обычные символы ASCII, в ином случае
предлагается, чтобы они сохранили особое значение – возникает двусмысленность.
Удобной формой
записи IP-адреса (
IPv4)
является запись в виде четырёх десятичных чисел со значением от 0 до 255,
разделённых точками. Стандарты, определяющие общий синтаксис URL, позволяют использовать
альтернативный способ записи IP-адреса с использованием нескольких систем
счисления (возможно, даже одновременно), например, IP-адрес 213.180.204.3 может
быть записан как
0325.0264.0314.03
(восьмеричная запись), 0xd5.0xb4.0xcc.0x3 (шестнадцатеричная запись)[3], 213.0264.0xcc.3
(смешанная: десятичная, восьмеричная и шестнадцатеричная формы записи). Кроме
того, браузеры могут принять Url-адрес с технически недопустимыми символами, а
затем, попытаться его проигнорировать или передать в первозданной форме,
например, DNS-клиенту, который либо отвергнет, либо пропустит такой запрос характерным
для операционной системы образом.
Особенно
интересный пример URL-анализа несовместимости адреса:
Перейдя в
браузере Firefox по ссылке, мы попадем
на страницу «Яндекса», хотя ожидали открыть страницу «Google».
В таблице 1 представлены отличия, которые должны учитываться:
Таблица 1
Описание
|
MSIE7
|
MSIE8
|
FF3
|
Safari
|
Opera
|
Chrome
|
Android
|
Символы, игнорируемые перед схемой URL
|
\x01-\x20
|
\x01-\x20
|
\t \r \n \x20
|
\x20
|
\t \r \n \x0B \x0C \xA0
|
\x00-\x20
|
\x20
|
Нестандартные символы, разрешенные в имени URL-схемы (за
исключением 0-9 A-Z a-z + - .)
|
\t \r \n
|
\t \r \n
|
\t \r \n
|
нет
|
\r \n +UTF8
|
\0 \t \r \n
|
нет
|
Нестандартные символы, остающиеся без изменений в строке
URL-запросов (за исключением 0-9 A-Z A-z- . _ ~ : / ? # [ ] @ ! $ & ' ( ) * + , ; =)*
|
" < >
\ ^ ` { | } \x7F
|
" < >
\ ^ ` { | } \x7F
|
\ ^ { | }
|
^ { | }
|
^ { | } \x7F
|
" \ ^ ` { | }
|
нет данных
|
Нестандартные символы, полностью игнорируемые в имени хоста
|
\t \r \n \xAD
|
\t \r \n \xAD
|
\t \r \n \xAD
|
\xAD
|
\х0а-\x0D \xA0 \xAD
|
\t \r \n \xAD
|
нет
|
Виды неполных или нецелых Url-адресов автоматически
исправляются до полного
|
//y \y \
|
//y \y \
|
//y x:///y x://[y]
|
//y \\y x:/y x:///y
|
//y \\y x://[y]
|
//y \y \x:///y
|
//y \y \
|
Является ли фрагмент ID (хэш), закодированный с применением
RFC в соответствии с вытекающими из URL правилами?
|
НЕТ
|
НЕТ
|
ЧАСТИЧНО
|
ДА
|
НЕТ
|
НЕТ
|
ДА
|
незарезервированная %nn-последовательности
URL-пути декодируются в адресной строке?
|
ДА
|
ДА
|
ДА
|
НЕТ
|
ДА
|
ДА
|
нет данных
|
незарезервированная %nn-последовательности
URL пути декодируются в location.href?
|
ДА
|
ДА
|
НЕТ
|
ДА
|
ДА
|
ДА
|
ДА
|
незарезервированная %nn-последовательности
URL-пути декодируются в текущих HTTP-запросах отправки?
|
ДА
|
ДА
|
НЕТ
|
НЕТ
|
НЕТ
|
ДА
|
НЕТ
|
Отклоненные символы в имени пользователя или пароле в URL (за
исключением / # ; ? :
% @)
|
\x00 \
|
\x00 \
|
нет
|
\x00-\x20" < > [
\ ]
^ ` { | } \x7f-\xff
|
\x00
|
\x00 \x01 \
|
\x00-\x20" < > [
\ ]
^ ` { | } \x7f-\xff
|
URL-данные аутентификации разделенные несколькими символами «@»
|
крайний левый
|
крайний левый
|
крайний правый
|
крайний левый
|
крайний правый
|
крайний правый
|
крайний левый
|
*Firefox 3.5 принимает
безопасный, но не совместимый с RFC подход представления в Url отдельного
символа «’» как %27, в дополнении к очередным
выходящим за рамки правилам.
ПРИМЕЧАНИЕ: Для борьбы
с фишингом многими браузерами вводятся
дополнительные ограничения на использование поля «логин» и «пароль» в Url-адресе;
см. раздел HTTP-аутентификация.
Пожалуйста, обратите внимание, когда ссылки внедрены в HTML-документы, декодирование HTML-объекта происходит перед тем, как ссылки анализируются. Поэтому, если в
URL-схеме символы игнорируются, ссылка вида javascript	:alert (1) может быть принята и выполнена как JavaScript равно как и javascript<TAB>:alert (1). Кроме того, некоторые символы, такие как \x00 в
Internet Explorer, или \x08 в Firefox, могут быть проигнорированы синтаксическим анализатором HTML,
если используется в некоторых местах, даже если они не относятся к обработке URL-кода
себя.
Примечание:
[1] - описание структуры данных, не
зависящее от аппаратной реализации и способа кодирования.
[2] – Так называемое URL-кодирование
или «percent-encoding».
[3] - Восьмеричные числа начинаются с цифры 0, после которой
следует серия цифр от 0 до 7. Шестнадцатеричные целые числа имеют префикс 0х
или 0Х и могут состоять из цифр от 0 до 9 и букв от а(А) до f(F).