Подделка заголовков HTTP запроса с помощью Flash ActionScript

Подделка заголовков HTTP запроса с помощью Flash ActionScript

Плохая идея доверять заголовкам HTTP запроса, которые посланы браузером. Фактически можно подменить любой заголовок, если клиента можно заставить запустить специально обработанный Flash ролик, и это возможно на более 80% компьютеров, подключенных к Интернет.

Amit Klein

Flash Player – популярное дополнение к браузеру от компании Adobe (изначально флеш был разработан Macromedia, которую позже купил Adobe). В этой статье рассматриваются Flash 7-й и 8-й версии, которые установлены более чем на 94% рабочих станций, имеющих выход в Интернет (согласно опросу NPD Online Survey в апреле 2006 года). Flash анимация поставляется в виде файлов SWF (ShockWave File). Adobe также разработал язык ActionScript, напоминающий Javascript, который используется внутри Flash роликов. ActionScript позволяет посылать произвольные HTTP запросы к произвольным сайтам через Web браузер, проигрывающий флеш-ролик. В результате можно сформировать запрос к сайту, который нельзя выполнить через обычный Javascript код. Также в запросе можно задать произвольные HTTP заголовки в исходящем HTTP запросе.

Посылаем произвольный HTTP заголовок через Flash  

Следующий синтаксис в ActionScript 2.0 позволяет послать GET запрос (в нашем примере на сайт http://www.vuln.site/some/page.cgi?p1=v1&p2=v2) с произвольным HTTP заголовком (Foo: Bar). Этот код работает с Flash 7 и 8 версии (возможно, работает и в 6-й версии):

var req:LoadVars=new LoadVars();
req.addRequestHeader("Foo","Bar");
req.send("http://www.vuln.site/some/page.cgi?p1=v1&p2=v2",
         "_blank","GET");


Похожий синтаксис используется для отправки POST запросов (с тем же самым заголовком, с телом запроса a=b&c=d):

var req:LoadVars=new LoadVars();
req.addRequestHeader("Foo","Bar");
req.decode("a=b&c=d");
req.send("http://www.vuln.site/some/page.cgi?p1=v1&p2=v2",
         "_blank","POST");


(Примечание: метод LoadVars.decode() был добавлен в Flash 7)

Запрос посылается из браузера, выполняющего Flash объект. Любые куки, которые обычно отправляет браузер, будут также посланы в этом случае. Посылается также User-Agent браузера и все стандартные заголовки браузера. Также поддерживаются HTTPS-запросы.
Эти примеры проверены и работают с Microsoft IE 6.0, Microsoft IE 6.0 SP2 и FireFox 1.5.0.4, с установленными Flash 8.0.22.0 и Flash 7.0.19.0 плагинами.

В IE также существует возможность переписать “нормальные” заголовки браузера, добавляя addRequestHeader с новым значением заголовка, в т.ч. заголовки Referrer и User-Agent. В FireFox 1.5.0.4, при использовании addRequestHeader(), заголовки будут добавлены к HTTP запросу.

// Один User-Agent в IE 6.0 SP2, 2 User-Agent в FF 1.5.0.4
req.addRequestHeader("User-Agent","Hacker/1.0");


// Один Referer в IE 6.0 SP2, два Referers в FF 1.5.0.4
req.addRequestHeader("Referer","http://somewhere/");


В IE, также можно переписать некоторые чувствительные заголовки, (например Host и Content-Length), добавляя двоеточие к имени заголовка:

req.addRequestHeader("Host:","foobar.site");

Этот метод не работает в FireFox 1.5.0.4.

Влияние на безопасность

Способность атакующего заставить браузер жертвы послать произвольные HTTP запросы к произвольным сайтам с произвольными HTTP заголовками воздействует на наше понимание безопасности Web приложений – как на оценку связанных с безопасностью явлений, так и на обоснованность некоторых механизмов безопасности.

Важно понять, что этот тип нападения по сути не является обычной XSS атакой, так как не воздействует на межсайтовое доверие внутри Flash объекта, или на доверие между Flash объектом и внедренной HTML страницей. Нападение лишь основывается на возможности послать запросы из Flash объекта к произвольному URL с произвольными HTTP заголовками. Такая возможность сама по себе является проблемой, так как позволяет атакующему посылать ссылку (к HTML странице внедренной в FLASH объекте, или непосредственно к Flash объекту, расположенному на Web сайте атакующего), которая выполнит флеш объект в браузере жертвы. Этот Flash объект пошлет HTTP запрос (с HTTP заголовками по выбору атакующего) к целевому Web сайту, и это, в свою очередь, поставит под угрозу безопасность браузер жертвы.

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

Пример 1 - "Expect" заголовок

Ранее была обнаружена уязвимость в Apache 1.3.34, 2.0.57 и 2.2.1, позволяющая внедрить HTML данные (включая произвольный Javascript код) через Expect заголовок. Однако производитель посчитал, что уязвимость невозможно поэксплуатировать, потому что не существует способа заставить браузер послать измененный Expect заголовок к целевому Web сайту. Однако, используя Flash объект, атакующий может заставить браузер послать такой запрос, заставив жертву кликнуть на ссылку http://www.evil.site/attack.swf. Этот URL содержит FLASH объект, который запустит следующий ActionScript код:

  var req:LoadVars=new LoadVars();
  req.addRequestHeader("Expect",
                       "<script>alert('gotcha!')</script>");
  req.send("http://www.target.site/","_blank","GET");


Этот ActionScript пошлет запрос из браузера жертвы к целевому Web сайту (www.target.site) с Expect заголовком, содержащим произвольный HTML (Javascript) код. Если целевой Web сайт работает на уязвимой версии Apache, то в результате будет возможно осуществить атаку межсайтового скриптинга. XSS атака возможна против Apache 1.3.34, 2.0.57 и 2.2.1, если браузер клиента IE или Firefox и поддерживает Flash 6/7+). В случае Apache 2.0/2.2, XSS ответ будет возвращен только после истечения времени ожидания (обычно несколько минут). Уязвимость устранена в последних версиях Apache – 1.3.35, 2.0.58 и 2.2.2 соответственно).

Пример 2 - CSRF и Referer

CSRF (Cross Site Request Forgery) атака позволяет атакующему заставить браузер жертвы выполнять различные действия (посылать HTTP запросы) на целевой сайт. Это редкий вид нападение, который всплывал несколько раз - впервые в списке рассылки Zope ("Client Side Trojans"), и несколько раз в BugTraq под именем CSRF. Обе ссылки советуют, кроме других методов, доверять HTTP Refferer заголовку, как очевидность того, что браузер посылает этот заголовок от ссылки, которая расположена на Web сайте. Действительно, используя возможности HTML+Javascript, почти невозможно подменить Referer (единственный способ описан в http://www.securityfocus.com/archive/1/411585, однако он работает в ограниченном подмножестве сценариев, и не работает, если используется HTTPS). Однако, как было показано выше, можно обойти эти ограничения, используя Flash, в т.ч. и для изменения заголовка Referrer в HTTPS ресурсах, используя браузер, который посылает куки сайта вместе с запросом. В результате могут быть посланы GET запросы (с произвольным хостом и частью запроса) и POST запросы (с произвольным хостом, частью запроса и телом в стандартном Content-Type формате "application/x-www-form-urlencoded").

Примечание: Существует множество других причин, по которым нельзя доверять заголовку Referrer, и это не первая статья, в которой предупреждается о порочности подобной практики.

Очевидно, что может быть подделан любой заголовок. В случае IE, заголовок, представленный браузером, может быть подменен атакующем (например, заголовок Referrer).

В случае браузера Firefox, заголовок Referrer подменить не получится, так как Firefox добавляет заголовок последним заголовком в HTTP запросе. Однако некоторые Web приложения могут использовать последние значения заголовка, и также могут быть уязвимыми к этому способу атаки.

В результате становится возможным эксплуатация любой рефлективной атаки межсайтового скриптинга, которая использует заголовки HTTP запроса (например Referrer, User-Agent, Expect, Host, Content-Type).

Flash 9

Flash 9 появился в 28 июня 2006 года (меньше месяца назад). В Flash 9, методика описанная выше (для класса LoadVars) не работает для любого заголовка представленного браузером (например, User-Agent, Host и Referrer), и скорее всего для других защищенных заголовков, типа Content-Length. Однако все равно могут быть посланы заголовки типа Expect, так что некоторые нападения (как в первом примере) все равно работают в Flash 9.

Ограничения методики

  • URL и часть тела запроса должны быть всегда URL-кодированы. Таким образом, невозможно вставить SP, HT, CR и LF ( и множество других символов) в URL и тело запроса.
  • Могут использоваться только GET и POST методы.
  • В IE может быть послан только один вариант каждого заголовка.
  • В целом нельзя полностью управлять параметрами заголовков, например атакующий может иметь проблемы пытаясь послать специальные символы внутри заголовков.

Частичное решение

Первое ограничение этой методики – невозможность послать CR и LF в теле запроса. Это означает, что методика не может использоваться для отправки POST запросов с "multipart/form-data" content-type форматом (этот формат использует сырые CR и LF чтобы отметить заголовки и границы). Другими словами, POST запрос, тело которого содержит поток "multipart/form-data", не может быть послан из Flash плеера. Авторы Web приложения, могут использовать HTML формы со свойством ENCTYPE установленным к "multipart/form-data", и предписывать, что POST запрос содержит тело multipart/form-data. Если используются эти механизмы, то невозможно осуществить нападения описанные выше.

Это решение конечно слишком навязчиво – должны быть изменены HTML страница и получаемый сценарий, чтобы использовать multipart/form-data. На многих средствах разработки Web приложений это просто реализовать, но на некоторых нет (например, ASP или Perl). Кроме того, в случаях описанных в примере 1, HTTP заголовок интерпретируется и используется Apache Web сервером, это решение не применимо.

Будущие направления

HTTP Request Splitting и HTTP Request Smuggling - в IE + Flash 7/8 возможно послать Content-Length заголовок с произвольным значением. Это позволяет выполнить HTTP Request Splitting нападение. Также внедряя Transfer-Encoding заголовок или второй Content-Length заголовок, можно осуществить нападение HTTP Request Smuggling. Необходимо произвести дополнительные исследования, чтобы разработать возможные методы эксплуатации этих атак.

Flash 9 – Хотя в Flash 9 наложены более строгие ограничения на создания заголовков через LoadVars.addRequestHeader(), возможности языка ActionScript 3.0 более богаты чем ActionScript 2.0. Например, возможно будет послать другие HTTP методы, не только GET или POST (например, WebDAV). Необходимо более тщательно изучить возможности Flash 9 и ActionScript 3.0, чтобы понять их потенциал в обработке HTTP запросов.

Заключение

Плохая идея доверять заголовкам HTTP запроса, которые посланы браузером. Фактически можно подменить любой заголовок, если клиента можно заставить запустить специально обработанный Flash ролик, и это возможно на более 80% компьютеров, подключенных к Интернет.

Ищем баги вместе! Но не те, что в продакшене...

Разбираем кейсы, делимся опытом, учимся на чужих ошибках

Зафиксируйте уязвимость своих знаний — подпишитесь!