Насколько безопасен HTTP_ORIGIN?
Я хочу узнать, поступает ли входящий вызов HTTP_REQUEST со стороннего веб-сайта из списка доменов, которые я определил.
Я знаю, что HTTP_REFERER можно использовать, чтобы узнать, где находится сторонний домен, но он недостаточно безопасен. Люди могут подделать его или использовать Telnet для фальсификации.
Итак, как насчет HTTP_ORIGIN? Это отправлено со всех браузеров? Это безопасно?
Кроме того, могут ли люди подделать REMOTE_ADDR в вызове HTTP_REQUEST?
7 ответов
HTTP_ORIGIN - это способ защиты от запросов CSRF (подделка межсайтовых запросов). В настоящее время он реализован только Chrome (по состоянию на ноябрь 2011 года). Я тестировал Firefox и Opera - но они провалились. Его имя в заголовке запроса - "Происхождение". На стороне сервера в моем скрипте php я вижу его как "HTTP_ORIGIN" в переменной $_SERVER. Этот заголовок отправляется только в некоторых случаях, когда требуется защита от CSRF (достаточно только POST). Вот список всех запросов, установлен ли он или нет:
https://wiki.mozilla.org/Security/Origin
Якорный тег - НЕТ
Оконная навигация - НЕТ
IMG - НЕТ
iframe, embed, applet - ДА
Форма (ПОЛУЧИТЬ и ПОСТИТЬ) - ДА
СЦЕНАРИЙ - ДА
таблицы стилей - НЕТ
зависимые нагрузки от таблиц стилей - НЕТ
Перенаправления - ДА
XHR - ДА
Исходный заголовок реализован только в Chrome, к сожалению. Впервые об этом было объявлено в январе 2010 года в блоге Google Chrome:
http://blog.chromium.org/2010/01/security-in-depth-new-security-features.html
Защита CSRF через заголовок источника
Заголовок Origin - это новая функция HTML5, которая помогает защитить ваш сайт от атак подделки межсайтовых запросов (CSRF). В CSRF-атаке вредоносный веб-сайт, например attacker.com, инструктирует браузер пользователя отправлять HTTP-запрос на целевой сервер, например example.com, который сбивает сервер example.com с какими-либо действиями. Например, если example.com является провайдером веб-почты, атака CSRF может подтолкнуть example.com к пересылке электронного письма злоумышленнику.
Заголовок Origin помогает сайтам защищаться от CSRF-атак, определяя, какой веб-сайт сгенерировал запрос. В приведенном выше примере example.com видит, что запрос поступил с вредоносного веб-сайта, поскольку заголовок Origin содержит значение http://attacker.com/. Чтобы использовать заголовок Origin в качестве защиты CSRF, сайт должен изменять состояние только в ответ на запросы, в которых либо (1) отсутствует заголовок Origin, либо (2) имеется заголовок Origin со значением из белого списка.
Я просто реализую защиту CSRF в своем php-скрипте, лично я использую Chrome, так что мне этого достаточно, я надеюсь, что другие браузеры скоро поймают chrome
Что забавно, так это то, что Mozilla изобрела эту функцию безопасности, так как вы можете прочитать много документации о заголовке Origin на его веб-сайте, но у них все еще не было времени на ее реализацию;-)
HTTP_ORIGIN, кажется, содержит только "протокол" и "домен", без косой черты в конце: " http://www.example.com/" - даже если вы отправили форму с " http://www.example.com/myform/".
Простая защита от CSRF в PHP-скрипте:
if ("POST" == $_SERVER["REQUEST_METHOD"]) {
if (isset($_SERVER["HTTP_ORIGIN"])) {
$address = "http://".$_SERVER["SERVER_NAME"];
if (strpos($address, $_SERVER["HTTP_ORIGIN"]) !== 0) {
exit("CSRF protection in POST request: detected invalid Origin header: ".$_SERVER["HTTP_ORIGIN"]);
}
}
}
Этот сценарий все еще можно обновить для поддержки PORT, отличного от 80 (Origin содержит порт, отличающийся от 80), HTTPS-соединения и отправки форм из разных поддоменов (например, sub.example.com => отправка запроса на www.example.com).
HTTP_ORIGIN
не отправляется всеми браузерами и не является безопасным.
Ничто, отправленное браузером, не может считаться безопасным.
Люди здесь думают, что все это неправильно - стандарт "CORS" не таков, чтобы сервер не был взломан, даже если это помогает в дополнение к тому, что он делает. Цель состоит в том, чтобы "БРАУЗЕР" мог упростить запросы, которые противоречат одной и той же политике происхождения. Если клиент и сервер находятся на одной странице, "КЛИЕНТ" может решить, разрешить или нет запрос.
Очевидно, что если сервер участвует в решении, которое вы помогаете в процессе обеспечения безопасности.
Но это не защитит сервер от несанкционированного доступа - вот для чего нужны пароли и куки.
Клиент может быть (как кто-то упомянул) инструментом telnet, где каждая созданная вещь является поддельной.
Но одно из преимуществ продаж Chrome, FF и т. Д. Заключается в том, что они помогут вам, не позволяя Javascript выходить за пределы одной и той же исходной песочницы, что означает, что по умолчанию единственное, что может быть скомпрометировано, - это то, что находится на собственный сайт злоумышленников. Или другие сайты, которые решили не быть в безопасности.
CORS - это технология, которая позволяет вам сказать - эй, я хочу, чтобы пользователи могли использовать мой шикарный сервис из javascript на этом другом сайте, который они используют. Так что я собираюсь добавить этот сайт в мои исключения. Это означает, что вы помогаете своим авторизованным пользователям пробить брешь в их безопасности браузера для этого конкретного сайта. Что означает дыру, которую может использовать хакер. Таким образом, забота, с которой вы создали службу, верно?
Это означает, что любой сайт, на котором не настроен CORS, по умолчанию защищен от межсайтовых сценариев из совместимого браузера (за исключением ошибок и взломов, конечно). Браузер спросит, хочет ли этот сервис участвовать в javascript исходного сайта, и если на этом межсайтовом сайте написано "Я ничего не знаю об этом проклятом сайте", то механизм javascript браузера закроет соединение и сбросит данные.
Итак, подведем итог: CORS не поможет вам обеспечить безопасность. Это поможет вам сделать дыру в ваших браузерах способной сделать пользователя более безопасным. Но, надеюсь, управляемым способом.. и только для конкретных сайтов..
HTTP - это текстовый протокол. ВСЕ заголовок запроса / структура тела могут быть подделаны, чтобы сказать что угодно.
Модернизированный:
function isOriginAllowed($incomingOrigin, $allowOrigin)
{
$pattern = '/^http:\/\/([\w_-]+\.)*' . $allowOrigin . '$/';
$allow = preg_match($pattern, $incomingOrigin);
if ($allow)
{
return true;
}
else
{
return false;
}
}
$incomingOrigin = array_key_exists('HTTP_ORIGIN', $_SERVER) ? $_SERVER['HTTP_ORIGIN'] : NULL;
$allowOrigin = $_SERVER['HTTP_HOST'];
if ($incomingOrigin !== null && isOriginAllowed($incomingOrigin, $allowOrigin))
{
exit("CSRF protection in POST request: detected invalid Origin header: " . $incomingOrigin);
}
Пример:
- http: // media.mydomain.com ИСТИНА
- http:// offline.mydomain.com ИСТИНА
- http:// domen1.mydomain.com ИСТИНА
- http:// domen_1.mydomain.com ИСТИНА
- http:// domen-1.mydomain.com ИСТИНА
- http: // ololomydomain.com FALSE
- http: // mydomain.com ИСТИНА
- http: // pro.mydomain.com ИСТИНА
- http:// super.pro.mydomain.com ИСТИНА
- http: // super.pro.fakemydomain.com FALSE
- http: // pro.fakemydomain.com FALSE
Обновление по состоянию на 2021 год:
HTTP_ORIGIN
почти полностью поддерживается всеми браузерами, см.: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin#browser_compatibility