HTML5 — будущий стандарт языка разметки Интернет. Пока он находится в стадии черновика, но все больше и больше его возможностей реализуются в популярных веб-браузерах. Но как это обычно бывает, новые технологии несут в себе и новые опасности, которые могут быть успешно проэксплоитованы. HTML5: краткое резюме Многие, вероятно, уже наслышаны про противостояние кодеков для технологии встраивания видеороликов на страницах. С помощью тега <video> предполагается если не заменить, то как минимум составить серьезную конкуренцию Adobe Flash. Заводя разговор о HTML5, часто вспоминают именно это нововведение. Еще бы: такие гиганты видеохостинга как Youtube и Vimeo уже реализовали поддержку новой технологии. А мобильные продукты от Apple, в которых официальной поддержки Flash'а не было и, скорее всего, не будет, уже активно ее используют. Так что потоковое видео, вставленное в страницу с помощью тега <video>, — это то, что можно пощупать уже сейчас. Среди других "вкусностей", которые предлагает HTML5 стоит выделить: * "Оффлайн" хранение данных в браузере – веб-хранилище, локальные БД; * Canvas 2D API; * Междоменное взаимодействие (Cross Domain Messaging); * "Drag-and-drop"-функционал; * Работа с сетью с помощью веб-сокетов; * Определение местоположения (Geolocation). Веб-хранилище — мощная альтернатива кукам Нет ничего удивительного в том, что с приходом эры веб-приложений (как например Gmail) появилась необходимость в хранении массивов данных на стороне веб-браузера. Яркий пример тому — это попытки сделать возможной работу с такими веб-приложениями офлайн. В этом больших успехов добился Google со своей технологией Google Gears. Куки со своими лимитами (особенно по размеру в 4КБ) и методами работы с ними — явно неподходящее и устаревшее решение для подобных задач. По этой причине было решено разработать новый механизм, подобный кукам, но лишенный их недостатков. Им и стала технология WebStorage. В 2 словах, благодаря HTML5 мы теперь имеем хранилище (вернее два хранилища) вида "ключ-значение" на стороне веб-браузера с доступом из JavaScript: * localStorage — для долговременного хранения данных; * sessionStorage — для сессионного применения. Механизм поддерживается практически всеми веб-браузерами: Firefox 3.5, Safari 4.0, IE8, Google Chrome, Opera 10.50. Ниже приведён типовой пример использования локального веб-хранилища для учёта посетителей веб-страницы. PHP: <p>Вы просматривали эту страницу <span id="count">сколько-то </span> раз.</p> <script> if (!localStorage.pageLoadCount) localStorage.pageLoadCount = 0; localStorage.pageLoadCount += 1; document.getElementById('count').textContent = localStorage.pageLoadCount; </script> Давай посмотрим на сторону безопасности данной технологии. Как и многое в JS API в HTML5 подчиняется механизму HTML5 Origin, то есть данные доступны для всех страниц на одном домене с учетом протокола и номера порта (например, example.com:80). Как уже отмечалось выше, веб-хранилище избавлено от лимита в 4КБ и спецификация рекомендует использовать 5 МБ на домен. На деле же у Firefox, Safari, Opera, Google Chrome лимит равен 5МБ, у IE — 10МБ. Но самое интересное не в самой квоте, а в том, как браузер используют их. К примеру, в Firefox действует лимит на домен третьего уровня .example.com. Таким образом, (и тут внимание!) один поддомен может полностью занять место, отведенное для домена: PHP: // Firefox 3.6.8 for (var i = 0; i < 100; i++) { try { localStorage.setItem(rand(1, 10000).toString() + 'foo'+i.toString(), 'AA...AA'+i.toString()); } catch (e) { alert(i.toString()+'|'+e);break; } } Не обошлось и без вездесущего null-байта. В данном веб-браузере вставка null-байта в ключ localStorage приводят к "забывчивости" Firefox. Иными словами место, хоть и всего в 1Б занято, но веб-браузер его не учитывает. "Мелочь, а приятно" (с). Идём дальше. Google Chrome пытается быть более строгим к ограничениям на домен и в расчете лимита учитывается полностью домен. Но в тоже самое время в Google Chrome можно занять вообще *всё* твое дисковое пространство, создав кучу айфреймов на wildcard-домен, в котором и забрать по 5МБ! PHP: for(var i=0; i<10; i++) { var iframe = document.createElement('iframe'); iframe.src = 'http://'+randomString()+'.example.com/ddos.html'; document.body.appendChild(iframe); } Этот баг до сих пор не исправлен. Помимо прочего от кук к новому виду хранилища перекочевали и старые проблемы, в том числе: * отслеживание пользователей; * DNS-спуфинг атаки. Из-за особенностей ограничения доступа (протокол+домен+порт) мы также имеем проблемы на хостингах, использующих систему example.com/~user/, чего к слову сказать с куками не было. Да, давно уже мы не встречали подобный хостинг в жизни, но вдруг! Стоит также отметить ещё одну важную особенность веб-хранилища — в отличие от кук на сервер ничего не передается в рамках привычных HTTP-запросов. Данные доступны только со стороны веб-браузера через JS API. Так же как и другие технологии, которые переносят большую часть работы веб-приложения на сторону веб-браузера, это повышает риски от традиционных уязвимостей вида XSS. И если раньше угоняли куки, то сейчас велик шанс угнать более "вкусные" данные, а в 5 МБ их уместить можно немало! Для сессионных кук, впрочем, появилась возможность сильно урезать их доступность с JavaScript с помощью атрибута HTTPOnly, и это хорошо. Но для WebStorage подобных механизмов не предусмотрено, и доступ будет полным. SQL-инъекция в веб-браузере Раз уж зашла речь про хранение данных вспомним и про ещё более продвинутое средство — веб-SQL база данных прямо в браузере! Пускай это и SQLite, но и это уже неплохо! Не будем подробно рассматривать достаточно специфичный синтаксис выполнения запросов к БД, а лучше сразу рассмотрим следующий код, который должен просто выводить информацию о книге по ее ID: PHP: function showById() { var pos = document.URL.indexOf("book=")+5; var bookId = document.URL.substring(pos,document.URL.length); var author = ''; var title = ''; db.transaction(function(tx) { tx.executeSql("SELECT * FROM books WHERE id = " + bookId, [], function(tx, result) { if ( result.rows.length > 0) { document.getElementById('bookAuthor').textContent =result.rows.item(0)['author']; document.getElementById('bookTitle').textContent = result.rows.item(0)['title']; } }, function(tx, error){}); }); } А что будет, если перейти по адресу вроде следующего? target.com/html5/websql.html?book=1/**/AND/**/1=2 Получаем DOMXSS+SQL-инъекцию! Жаль, что возможности по использованию данной уязвимости достаточно малы (кстати, Oxod написал хорошую статью про инъекции в SQLite, ссылку ищи внизу). Особенно с учётом того, что и Опера, и Хром хранят в отдельных файлах sqlite-базы для сайтов. Само собой авторы предусмотрели возможность и рекомендуют выполнять "безопасные" параметризированные SQL-запросы. Но посмотрим, как разработчики будут следовать их совету. Помимо прочего для веб-SQL баз характерны такие же проблемы, как у localStorage и sessionStorage. Новые теги и атрибуты — обновляем базы сигнатур IDS и WAF В HTML5 добавились новые теги и атрибуты — это значит, что пора обновлять правила/сигнатуры твоих WAF (мы подробно писали о файрволах для веб-приложений них в статье "Горящие стены защиты" в #10/2009 номере ][ ). Одним из новых элементов разметки является атрибут autofocus. Это достаточно долгожданный атрибут, потому как ранее, практически все время приходилось делать JavaScript-обработку автофокуса. И в вот в HTML5, наконец, добавили атрибут для автофокусировки на определённом текстовом поле. Но давай представим себе использование этого атрибута как способа автоматического исполнения кода: PHP: <input onfocus=alert(1) autofocus> <input onblur=write(1) autofocus><input autofocus> Этот приём может пригодиться, например, когда фильтруются угловые скобки. Тег <video>, который мы уже сегодня вспоминали, несет в себе помимо собственно мультимедийных функций ещё и возможности выполнения JavaScript-кода (кто бы мог подумать через атрибут poster: PHP: <video poster=javascript:alert(1)// <video><source onerror="javascript:alert(1)"> К "заслугам" <video> можно отнести еще и возможность точной идентификации веб-браузера. Будет еще одним приемом в копилке Metasploit Decloak. Примеры c новысми элементами можно продолжать. Как тебе, например, самовыполнение JavaScript с помощью обработчика onscroll тега и всё того же атрибута autofocus? PHP: <body onscroll=alert(1)><br><br><br>...<br><input autofocus> Или вот еще финт, правда он работает пока только в последних версиях Оперы: PHP: <form id="test" /><button form="test" formaction="javascript:alert(1)"> Новые типы полей форм Помимо новых тегов и атрибутов, в HTML5 большое внимание уделено взаимодействию веб-приложений с пользователем и добавлено большое количество типов текстовых полей ввода: datetime, datetime-local, date, month, time, week, number, range, email, url, search, tel, color. Они призваны добавить больше смысловой нагрузки обычным текстовым полям. Так для поля date будет возможно удобно выбрать дату, не прибегая к использованию готовых календарей на JavaScript. Не придется больше заморачиваться с текстом-заглушкой. В общем, наконец, появятся более удобные и подходящие по контексту средства ввода информации. PHP: <style> [required] { background-color: green; } :invalid { background-color: red; } </style> … <input name="email" type="email"/> Что важно с точки зрения безопасности, так это то, что поля будут сами себя валидировать! Валидация данных в формах С одной стороны, ура — больше не надо писать регулярки по RFC (хотя и у тебя этого права никто не отнимает, благо теперь добавлен специальный атрибут pattern) и заморачиваться опять же проверками на JavaScript перед отправкой данных формы на сервер. С другой стороны не следует забывать про валидацию на стороне серверной части веб-приложения! Как ни странно, но практика показывает, что и сейчас часто встречаются случаи, когда про серверные проверки забывают или реализуют их недостаточно строго. Проверке на стороне веб-браузера, как понимаешь, доверять уж точно не стоит. Особенно "замылиться глаз" может при разработке AJAX-части современных веб-приложений. И вот чего я опасаюсь: если эта валидация ещё больше упростится, то как бы разработчики и вовсе про нее не забыли! Cross-document messaging Веб-браузеры по причинам безопасности ограничивают взаимодействие (доступ и обмен данными) клиентских частей веб-приложений, размещенных на разных доменах. Несмотря на то, что ограничение вроде как действительно нужное с точки зрения безопасности, междокументное взаимодействие в некоторых случаях часто оказывается необходимым. Например, это может быть актуально для виджетных технологий. Система междокументных сообщений позволяет (в идеале) безопасным способом обмениваться данными документам, размещенным на разных доменах, и поддерживается уже как минимум Firefox, Google Chrome. Рассмотрим, как работает данный механизм. Пусть сайт (вернее его клиентская часть) example.com/index.html хочет взаимодействовать с foo.com/iframe.html, который загружен в айфрейме. В таком случае на foo.com инициализируется "получатель" сообщений. Код получателя сообщений на foo.com: PHP: <div id="msg">...</div> <script> window.addEventListener('message', receiver, false); function receiver(e) { if (e.origin != 'http://example.com') { return; } document.getElementById('msg').innerHTML = 'Origin: ' + e.origin + ' From: ' + e.source + ' Data: ' + e.data; } </script> Обрати внимание на явную проверку отправителя (e.origin). Но даже с такой проверкой надо не забывать валидировать пришедшие данные на тот случай, если на доверенном отправителе вдруг обнаружится, скажем, XSS. А в документе (клиентской части) a.example.com мы отправляем сообщение получателю: PHP: function postMsg() { var o = document.getElementById('ifra'); o.contentWindow.postMessage(document.getElementById('msg').value, 'http://foo.com/'); return false; } Здесь важно явным образом указывать адресата сообщения targetOrigin. Даже не смотря на то, что стандартом предусмотрена возможность указать "*" и тем самым разрешить отправлять сообщения любому адресату. Имхо, основной риск в этом механизме в изначальной сложности безопасной реализации обмена сообщениями. Разработчику нужно чётко понимать, что он делает. ТВелик риск элементарно забыть про проверку отправителя. Может оказаться опасным "слепое" использование пришедших данных, что приведет к перерождению DOM-based XSS. Определение местоположения Текущие местоположение — достаточно важный аспект частной жизни ("приватности"), поэтому реализовывать механизмы его определения надо с большой осторожностью. Этот аспект описан в секции "Security and privacy considerations" спецификации от W3С. Если в двух словах, то в спецификации заявлено о том, что месторасположение должно быть явным образом разрешено посетителем сайта. Технически это реализуется вызовом специального метода объекта navigator.geolocation: PHP: if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( function(position) { var lat = position.coords.latitude; var lng = position.coords.longitude; var options = {position: new google.maps.LatLng(lat, lng)} var marker = new google.maps.Marker(options); marker.setMap(map); }); } Во всех популярных браузерах (за исключением MS Internet Explorer, в котором Geolocation API попросту не реализован) при заходе страницу, использующую гелокацию, отображается предупреждение о сборе сведений и спрашивается разрешение у пользователя. При этом есть возможность запомнить свой выбор и/или поместить сайт в белый либо чёрный список. Важно, что при этом учитывается домен сайта, не включая полный путь до скрипта… В ходе определения местоположения веб-браузер собирает данные о твоем IP-адресе, ближайших точках беспроводного доступа и возможно другую подобную информацию (например, случайный идентификатор клиента назначаемого Google, который истекает через 2 недели) и пересылает это всё сервису определения местоположения. А теперь, братья-параноики, угадайте, кто будет являться этим самым сервисом в большом количестве случаев (Google Chrome, Firefox, Opera)?! Правильно, Google Location Services! Нам, конечно обещают, что: "Ни Mozilla ни Google никогда не будут использовать собранную Google Location Services информацию для вашей идентификации и никогда не будут за ваши шпионить." Но мы то знаем, что никому нельзя верить! Так же следует обратить внимание на печальные последствия, которые принесёт XSS на разрешенном для сбора координат сайте. В заключение Хочется надеяться, что наученные горьким опытом разработчики веб-приложений не только кинутся реализовывать все действительно интересные и нужные фишки HTML5, но и проштудируют разделы "Security" соответствующих спецификаций. Радаует, что не отстают от прогресса и различные инструменты для пентестеров, в том числе W3AF, являющийся мощным и свободный фреймворком для проведения аудита безопасности веб-приложений. Ваш покорный слуга является одним из участников этого проекта и мы уже добавили модули для поиска мест использования WebStorage и другие рискованные участки кода. Так что при очередном аудите сайта на безопасность ты можешь определить, используются ли там фишки HTML5 . ________________________ http://www.xakep.ru/post/54223/
ИЗВРАТ HTML 5 - здравствуй новые глюки, баки, потери памяти и просто брейнфак. Хватает уже что почта.ру после объединения с qip взяла дебильный интерфейс и Гугл туда же стремится... теперь пользуюсь только софтом по POP3 и SMTP На будущее: пока не научитесь чистить localStorage - даже не думайте о своей анонимности. Куки просто нервно курят ТС'у респект за перепечатку но заголовки типа "SQL-инъекция в веб-браузере" надо біло бі сделать заголовками или хоть отделить