Pull to refresh

Comments 26

Одного не понимаю. Как вы с помощью редиректа заставите браузер отдавать нужный вам host?
А нормальный вебсервер отдаст вам 404 Not Found, потому что у вас там настроен виртуалхост на определённый домен.
Зачем так делать?
src="<?=$_SERVER['HTTP_HOST'] ?>/my.js"
Из рубрики, как делать — не надо.
Достаточно же "/my.js"…
Ну, если есть сомнения, что my.js с чужого хоста сработает, попробуйте сделать так:
document.write('<script>window.setTimeout(function() { alert(document.cookie) }, 2000);</script>');
Поиграл немного с заголовками и редиректами. Теоретически, чтобы описанный метод сработал, надо чтобы "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: Не удается отобразить эту страницу
Да, весь фокус в заголовках. Но ведь и редирект можно сделать по-разному. Насколько я знаю, ява апплеты умеют передавать произвольные заголовки
Приведите пожалуйста рабочий пример такого редиректа, выше вас уже просили об этом. Руками через telnet или curl естественно можно любые заголовки указать.
Точно также проверил Ваш метод — ни в одном браузере он не работает. Браузеры ругаются/молчат и не отдают содержимое (Apache 2.x, PHP 5.x, Firefox, Chrome)
Java-аплеты тут не причем — мы тут про браузеры говорим, а не про встроенные объекты (ибо там вообще можно все что угодно можно сделать и любой заголовок подмешать).

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


Возможно, меня не правильно поняли. Я имел в виду именно конечный результат, основанный на том, что php использует именно HTTP_HOST. А как пхп получит подобные заголовки, хоть встроенными объектами, хоть еще как-нибудь, мне, по сути, не важно.
Тут люди требуют чистого эксперимента, сразу скажу, что я не хацкер, поэтому получив подобную идею я просто перестраховался от подобной уязвимости, введя в код разрешенные хосты и НЕ ПЫТАЛСЯ эту уязвимость реализовать. Хотя, теперь вижу, что зря и постараюсь эту ошибку исправить в ближайшее время. Тем не менее, важно другое — сама идея довольно проста по меньшей мере для понимания. Это не редкость, когда один человек давал теоретическое обоснование уязвимости, а другой приводил реализацию (начал все мужик, который заявил, что Земля вертится).
Я, конечно, попытаюсь вникнуть в новую для меня область разработки аплетов, но независимо от того, получится у меня, как у новичка или нет — вы не расслабляйтесь (потому, что не факт, что не получится у кого-то другого). И, я еще раз подчеркну смысл всей этой статьи — это касается именно вариантов использования PHP кода.
Вот честное слово, только-только было собрался состряпать образец, как наткнулся на старую статью еще за 2006 год. Это как раз то, о чем я говорю, была б идея, реализация найдется: http://www.securitylab.ru/analytics/271169.php Конечно, новые версии плеера не позволяют отправлять критические заголовки, но автор правильно подметил, что есть еще Action Script, чьи возможности довольно широки в этом плане http://kharchuk.ru/as3/URLRequestHeader.html. Так что, как я уже говорил, вопрос не в том, как кто-либо сделает редирект на наш скрипт, с помощью апплета, устаревшей версии плеера, с помощью Action Script или в комбинации этих методов. Важно то, как поведет себя наш PHP сценарий. Вот о чем я хотел вам сказать.
Серьезно? Кто то ставит именно такие ссылки?
ну, например, в laravel многие ссылки пишутся через {{ url('/my.js') }}, что приобретает вид 'http://user.com/my.js'
А, а вот тут как раз в точку. И не только laravel. Как вы все знаете, был принят стандарт PSR-7, в котором есть объект, реализующий UriIntrface. И как заманчиво будет сделать следующее:
$request = ServerRequestFactory::make();
$uri = $request->getUri();

И потом использовать это в ссылках. А то, что при этом там будет присутствовать хост, причем взятый именно из заголовков, кто будет разбираться в таких подробностях?
— В laravel используется компонент из symphony. Как можно заметить, там куча проверок со словом trusted в названии.

— Как именно будет работать $request->getUri() зависит от реализации. Если кто-то сделает небезопасную реализацию, которая просто возвращает HTTP_HOST как есть без всяких проверок, значит тот кто разрабатывал и тот кто использует сам себе злобный буратино.

— Уровень опасности от такого использования заголовков примерно такой же, как если бы кто-то в HTML коде написал
<?= $_GET['id'] ?>
а мы бы в id передали код на javascript. Это не уязвимость в HTTP_HOST или в PHP. Просто не надо выводить недоверенные неэкранированные данные.
Что-то народ затих, наверное, колдуют над Action Script. Черт, вот нужно было промолчать.
В корзину абсолютные ссылки! Для статики и фреймов они не нужны вовсе…
Ух, наминусовали :) Самое интересное, что минусуют совсем не те, кто хочет защитить свой код.
Вот вам, господа, информация к размышлению:
Из доков по контексту http в php
request_fulluri boolean

Когда установлено в TRUE, весь URI будет использован при построении запроса. (Например, GET www.example.com/path/to/file.html HTTP/1.0). Хотя это нестандартный формат запроса, некоторые прокси-серверы требуют его.

По умолчанию значение FALSE.


Грубо говоря, здесь речь идет как раз об абсолютной форме HTTP target.
То есть, чтобы вам для воспроизведения уязвимости не пришлось переписывать исходники nginx, попробуйте просто сделать вот так:
`
<?php
$opts = array(
  'http'=>array(
    'method'=>"GET",
    'request_fulluri' => true,
    'header'=>"Host:www.hacker.com\r\n"
  )
);

$context = stream_context_create($opts);

$fp = fopen('http://www.user.com/script_to_hack.php', 'r', false, $context);
if (! $fp) {
  exit('error');
}

$contents = stream_get_contents($fp);
fclose($fp);
echo $contents;
`
Это все еще не раскрывает того, как именно получится сделать редирект на user.com с неправильным Host. Проблема ведь не в том, чтобы отправить запрос — это можно хоть telnet-ом сделать, вся мякотка в том, что нужно это уговорить сделать браузер, который будет у конечного пользователя, чьи куки вы безуспешно пытаетесь спереть.
Поэтому, пожалуйста, покажите PoC.
А, простите, туплю под вечер. Просто пол дня убил, чтобы сначала апач, а потом nginx заставить работать как прокси именно с использованием абсолютного target, а когда уже полез в исходники nginx_http_proxy_module.c, сообразил, что такое просто не предусмотрено конструкцией :) Ну и да, при "подтягивании" контента php файлом куки-то мы не получим. Нет, мы их, конечно, получим с помощью var_dump(stream_get_meta_data($fp)); Но нам же нужно взять из браузера действительное значение для атакуемого домена, а он нам их не даст, тут вы правы. Ладно, я еще подумаю.
минусуют совсем не те, кто хочет защитить свой код.

Те, кто хочет защитить свой код, просто запрещают серверу отвечать на чужие Host, что делает вашу "уязвимость" неприменимой вне зависимости от серверного языка и фреймворка.
Да я и не говорю, что защита на уровне настроек сервера не работает. Она работает. Но вы даже сами делите (поскольку это очевидно) оценку системы на серверные настройки, серверный язык и фреймворк. Вспомните теорию надежности "надежность системы определяется надежностью самого слабого звена". То есть да, защита на уровне настроек сервера работает, но если она "закрывает" дыры в программном коде, то это не повышает оценку надежности системы в целом. И это будет невеселая картинка, когда фреймворк является "слабым звеном системы". Как-то так.
То есть да, защита на уровне настроек сервера работает, но если она «закрывает» дыры в программном коде, то это не повышает оценку надежности системы в целом.

Не повышает, но и не понижает. Вы заведомо не можете закрыть все вещи на уровне фреймворка, потому что над какими-то вещами у него нет контроля. Не используя ограничение на Host, вы вынуждены писать свои собственные велосипеды, которые не факт, что будут надежнее.
Если это и работает (в чём выше в комментах проверившие сомневаются) то именно куки вы всё равно не получите на нормальном сайте, потому что они будут httponly. Хотя, конечно, потенциальный запуск js неприятен и всё равно опасен.
Sign up to leave a comment.

Articles