На Хабре уже упоминали об одной известной уязвимости, связанной с переменной $_SERVER['HTTP_HOST']. Только почему-то говорилось об SQL-инъекциях и о чем угодно, кроме XSS.

Возможности комментировать исходную статью у меня нет, поэтому в двух строках уточню. Допустим, у вас на сайте есть ссылки с абсолютным адресом, вида:

<script type="text/javascript" src="<?=$_SERVER['HTTP_HOST']  ?>/my.js"></script>

Допустим, адрес вашего сайта "www.user.com". Допустим, адрес моего сайта "www.hacker.com". Все, что мне нужно сделать, — это скинуть вам ссылку на специальную страницу моего сайта, откуда я сделаю самый обычный редирект на ваш же собственный сайт. Только для редиректа использую немного необычные заголовки. В качестве HTTP-target я укажу ваш собственный сайт "www.user.com", а вот в качестве хоста — мой "www.hacker.com". Хотя, в принципе, в абсолютной форме HTTP-target нет ничего необычного.

Заголовки примут вид:

GET http://www.user.com HTTP/1.1
Host:www.hacker.com

И ваш скрипт вместо SERVER['HTTP_HOST'] подставит мой хост. Ваша ссылка src="<?=$_SERVER['HTTP_HOST'] ?>/my.js" примет вид не как вы ожидали "www.user.com/my.js", а "www.hacker.com/my.js". В результате чего с моего сайта ваш браузер с чистой совестью скачает скрипт и выполнит его.

А я получу ваши cookie.

Вы навскидку скажете, что у вас нет абсолютных ссылок? Ну, во-первых, как минимум TinyMCE по умолчанию использует абсолютные ссылки. Кроме того, не обязательно это должна быть ссылка на *.js Ссылка на css тоже годится. Ну, или в крайнем случае, на iframe.
Поэтому, как обычно, никогда на доверяйте данным, пришедшим от клиента.

Комментарии (25)


  1. ganjar
    22.03.2016 00:57
    +4

    Одного не понимаю. Как вы с помощью редиректа заставите браузер отдавать нужный вам host?


  1. librarian
    22.03.2016 01:27
    +7

    А нормальный вебсервер отдаст вам 404 Not Found, потому что у вас там настроен виртуалхост на определённый домен.


  1. sayber
    22.03.2016 03:31
    +5

    Зачем так делать?
    src="<?=$_SERVER['HTTP_HOST'] ?>/my.js"


    1. ManInBlackHat
      22.03.2016 11:19
      +1

      Из рубрики, как делать — не надо.
      Достаточно же "/my.js"…


      1. DamonEs
        22.03.2016 11:21

        Ну, если есть сомнения, что my.js с чужого хоста сработает, попробуйте сделать так:
        document.write('<script>window.setTimeout(function() { alert(document.cookie) }, 2000);</script>');


  1. mwizard
    22.03.2016 05:12
    +3

    А можно PoC?


  1. michael_vostrikov
    22.03.2016 09:10
    +4

    Поиграл немного с заголовками и редиректами. Теоретически, чтобы описанный метод сработал, надо чтобы "hacker.com" и "user.com" находились на одном хостинге, а браузер принимал редирект вида:
    Location: http://www.hacker.com http://www.user.com

    Тогда "www.hacker.com" попал бы в "Host", а строка " http://www.user.com" (с пробелом) считалась бы страницей и попала в "GET".

    Браузеры такой редирект не принимают, реакция следующая:
    Firefox: Firefox не может найти сервер www.hacker.com%20http
    Chrome: Не удается найти DNS address сервера www.hacker.com%20http
    IE: Не удается отобразить эту страницу

    Если попытаться как-то модифицировать URL:
    Location: http://www.hacker.com:http://www.user.com

    то реакция будет такая:
    Firefox: Ошибка искажения содержимого
    Chrome: [молча ничего не загружает]
    IE: Не удается отобразить эту страницу


    1. DamonEs
      22.03.2016 11:09
      -2

      Да, весь фокус в заголовках. Но ведь и редирект можно сделать по-разному. Насколько я знаю, ява апплеты умеют передавать произвольные заголовки


      1. michael_vostrikov
        22.03.2016 12:00
        +4

        Приведите пожалуйста рабочий пример такого редиректа, выше вас уже просили об этом. Руками через telnet или curl естественно можно любые заголовки указать.


      1. ionicman
        22.03.2016 12:09
        +2

        Точно также проверил Ваш метод — ни в одном браузере он не работает. Браузеры ругаются/молчат и не отдают содержимое (Apache 2.x, PHP 5.x, Firefox, Chrome)
        Java-аплеты тут не причем — мы тут про браузеры говорим, а не про встроенные объекты (ибо там вообще можно все что угодно можно сделать и любой заголовок подмешать).

        Еще раз — Ваша уязвимость не воспроизводится.
        Вы можете выложить рабочую версию скрипта, где воспроизводится данная уязвимость?



        1. DamonEs
          22.03.2016 13:35
          -3

          Возможно, меня не правильно поняли. Я имел в виду именно конечный результат, основанный на том, что php использует именно HTTP_HOST. А как пхп получит подобные заголовки, хоть встроенными объектами, хоть еще как-нибудь, мне, по сути, не важно.
          Тут люди требуют чистого эксперимента, сразу скажу, что я не хацкер, поэтому получив подобную идею я просто перестраховался от подобной уязвимости, введя в код разрешенные хосты и НЕ ПЫТАЛСЯ эту уязвимость реализовать. Хотя, теперь вижу, что зря и постараюсь эту ошибку исправить в ближайшее время. Тем не менее, важно другое — сама идея довольно проста по меньшей мере для понимания. Это не редкость, когда один человек давал теоретическое обоснование уязвимости, а другой приводил реализацию (начал все мужик, который заявил, что Земля вертится).
          Я, конечно, попытаюсь вникнуть в новую для меня область разработки аплетов, но независимо от того, получится у меня, как у новичка или нет — вы не расслабляйтесь (потому, что не факт, что не получится у кого-то другого). И, я еще раз подчеркну смысл всей этой статьи — это касается именно вариантов использования PHP кода.


  1. scronheim
    22.03.2016 11:07

    Серьезно? Кто то ставит именно такие ссылки?


  1. fog
    28.03.2016 21:56

    Если это и работает (в чём выше в комментах проверившие сомневаются) то именно куки вы всё равно не получите на нормальном сайте, потому что они будут httponly. Хотя, конечно, потенциальный запуск js неприятен и всё равно опасен.