Задать вопрос
xenon
@xenon
Too drunk to fsck

Есть ли здесь реальная reflected XSS или это false positive (безопасно ли включать URL запроса в код страницы)?

Может быть написал сумбурно, но ниже дополнение, которое упрощает все до одной строчки PHP (если ли здесь XSS?):

<?php
echo($_SERVER["REQUEST_URI"]);
?>


Тестирую один сервер, есть у него такая интересная штука, при обращении к /path/script.php?t=1165 в ответе:
<input type="hidden" name="url" value="/path/script.php?t=1165">

А это - именно то, что мы в адресе ставим ведь! Делаем t=1165zzz, и в ответе эти zzz появляются. А дальше интересное.

$ curl -is 'https://example.com/path/script.php?t=1165"><script>alert(11111)</script>zzzzz'  | grep 11111
<input type="hidden" name="url" value="/path/script.php?t=1165"><script>alert(11111)</script>zzzzz">
<input type="hidden" name="url" value="/path/script.php?t=1165"><script>alert(11111)</script>zzzzz">

(аж два раза упоминается)

Что мы получили? Да это же вроде reflected cross-site scripting уязвимость! Можем заманить юзера на специальный URL (типа вот такого вот) и выполнить JS код в его контексте! украсть куки или послать запрос который он может только послать. Ура (вроде бы).

Но... пробую через httpie и хренушки.
http -pHb 'https://example.com/path/script.php?t=1165"><script>alert(11111)</script>zzzzz' | grep zzz
GET /path/script.php?t=1165%22%3E%3Cscript%3Ealert(11111)%3C/script%3Ezzzzz HTTP/1.1
<input type="hidden" name="url" value="/path/script.php?t=1165%22%3E%3Cscript%3Ealert(11111)%3C/script%3Ezzzzz">
<input type="hidden" name="url" value="/path/script.php?t=1165%22%3E%3Cscript%3Ealert(11111)%3C/script%3Ezzzzz">


Я специально указал, чтобы он мне выводил хидеры запроса, включая сам GET. И мы видим, что сайт-то тупой, он по прежнему просто отражает все, что мы ему послали, не проверяя этого. Беда в том, что клиент (httpie) умный и эскейпит все наши опасные кавычки и скобочки. И такая же фигня при попытке отправить из браузера. (слеш могу передать, но одинарные и двойные кавычки, больше-меньше - hex-кодируются во всякие t=1165zzzzz\%22\\%22\\\%22\\\\%22%3C%3E%27%27%27. Уязвимость только через curl удалось воспроизвести. (Может какие-то старые браузеры еще так же будут себя вести?)

Пробовал POSTом отправить это значение t, но отражается именно запрос, так что ничего, что мы вложили в t там нет.

Пока что наиболее близкое по теме нашел вот здесь:
https://security.stackexchange.com/questions/22567...

Адрес сервера давать не хочу, но любые идеи попробовать могу.

Вопрос 1: Можно ли это как-то обойти, обхитрить?
Вопрос 2: Это поведение веб-клиентов - "хороший тон" (кто-то кодирует кавычки в хекс, а кто-то нет) или RFC номер такой-то обязывает кодировать?
Вопрос 3: Если на 1 ответа нет, или ответ "нет", то значит ли это, что в веб разработке всегда можно безопасно включать URI запроса в ответе?

Дополнение
Дополню кое-что. Это наш сервер (у меня и так есть к нему доступ, но я проверяю его), и я сделал простой заведомо уязвимый скрипт:
<?php
echo($_SERVER["REQUEST_URI"]);
echo($_REQUEST["t"]);
?>


При запросе к /_xss-test.php?t=...<b>bold</b>... имеем:

/_xss-test.php?t=...%3Cb%3Ebold%3C/b%3E......bold...

Второй bold (который из t берется) - все-таки жирным пишется. То есть, хоть браузер и кодирует наш адрес, при запросе параметра он берется раскодированный, а вот при запросе REQUEST_URI - остается с "процентами"... . Ну и вложение JS кода через параметр t тоже получается (но не через REQUEST_URI).

И задача упрощается до - есть ли XSS уязвимость в скрипте вида:
<?php
echo($_SERVER["REQUEST_URI"]);
?>

Точно так же у меня получается от этого скрипта получить XSS через curl, но не через httpie или браузер.
  • Вопрос задан
  • 230 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 2
На практике в современных браузерах этот вектор в XSS не эксплуатируется из-за URI энкода. Последними популярными браузерами где этот вектор был эксплуатируем были IE 6/7, они не URI-енкодили GET-параметры при редиректе. Однако вставка URI без HTML-енкода в любом случае является ошибкой, даже если не приводит к XSS, например по стандарту должен HTML-енкодиться символ &, который может присутствовать в урлах.
Ответ написан
xenon
@xenon Автор вопроса
Too drunk to fsck
Сам себе отвечу.
1. В том браузере, который (как у меня) кодирует скобки-кавычки - проэксплойтить эту уязвимость нельзя. Кодирование есть на стороне браузера.
2. Это "хороший тон", RFC3986, секция 2.2 https://datatracker.ietf.org/doc/html/rfc3986#sect... обязывает кодировать только некоторые другие символы:

If data for a URI component would conflict with a reserved character's purpose as a delimiter, then the conflicting data must be percent-encoded before the URI is formed.

reserved = gen-delims / sub-delims

gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"

sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="


Никакого другого требования кодировать я не нашел. То есть, curl, когда не кодирует двойные кавычки и угловые скобки - действует строго по RFC, а вот httpie или браузер - сами кодируют "лишние" символы, но они не обязаны делать это.

Ну и главное тут - это происходит на стороне клиента, следовательно: 1) на стороне клиента может быть что-то поломаное, работающее с ошибкой. Может быть какой-то новый (новорожденный) браузер с этими проблемами. Может быть старый очень браузер. Могут быть какие-то особые настройки, сочетания настроек и дополнений, из-за которых он не делает так. и 2) Браузер вполне может исполнять только требования RFC, но не более. Защищать дырявое приложение от XSS атак он не обязан.

3. Включать REQUEST_URI в ответ неправильно. Лучше так не делать. Но, тем не менее, есть такой тонкий и негарантированный слой защиты в популярных браузерах, который защищает от этого. Но никто не дает никаких гарантий, положиться на это нельзя.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы