Контроль данных из формы

Статус
В этой теме нельзя размещать новые ответы.

ForJest

- свежая кровь
{}
Полная версия топика здесь
Здесь выжимки и совсем немного флейма, для того, чтобы было легче читать.
{}
HTTP_REFERER стоит проверять. Потому что возможна ситуация хака скриптов:
1. Человек авторизован на каком-нибудь сервисе service.com
2. Он нажимает ссылку, которую ему дали и уходит на другой хост hack.net
3. Страница hack.net формирует POST запрос согласно логике приложения service.com (с помощью hidden полей и JS самбита формы) и отправляет его на service.com. Это может быть допустим смена пароля. Или очистка всех сообщений. Или мало ли ещё что.
4. Запрос приходит на service.com из браузера авторизованного пользователя. Соответственно система принимает его и обрабатывает, если не обработан HTTP_REFERER/
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: ForJest
3. Страница hack.net формирует POST запрос согласно логике приложения service.com (с помощью hidden полей и JS самбита формы) и отправляет его на service.com. Это может быть допустим смена пароля. Или очистка всех сообщений. Или мало ли ещё что.
Страница hack.net формирует и отправляет POST запрос на стороне сервера, подставляя туда произвольный REFERRER, ага?
 

ForJest

- свежая кровь
Sad Spirit
Нет. REFERRER остаётся от страницы hack.net. В том то и дело, что если он не проверяется, скрипт об этом не узнает. Или ты что-то другое имел ввиду?
SiMM
Я об этом прекрасно знаю. Какой смысл в твоём высказывании, применительно к моему посту? Я хочу услышать объяснения.
 

ForJest

- свежая кровь
crocodile2u
:)))
В ЖЖ бытовала такая игра - змейка. Кликаешь на ссылочку и у тебя в жж пишется развесёлый пост, без твоего участия. Эта дырка была доступна именно потому, что умные люди, которые разрабатывали скрипт предположили, что реферер проверять без толку.
Проверка копеечная, а разговоров много.
Дальше - я как и ты читал эту статью. Реферер - это дополнительная мера безопасности. Безопасности от чего - смотри мой первый пост, чтобы понять сценарий.
--------------------
Ладно. Я уже устал повторять. Я скажу просто - HTTP_REFERER проверять нужно.
 

ForJest

- свежая кровь
crocodile2u
У меня создалось впечатление, что ты не в состоянии понять идею изложенную в
http://phpclub.ru/talk/showthread.php?postid=366315#post366315
Создалось у меня оно согласно твоему посту
http://phpclub.ru/talk/showthread.php?postid=366579#post366579
-------------------
Вероятно я не достаточно развёрнуто выразился. Из уважения к собсвенному уже проделанному труду по донесению ин-ции в массы я попытаюсь довести эту идею до тебя.
-------------------
И все-таки, проверка реферера в этом случае, по-моему, дело гиблое. Если перед обработкой формы есть проверка, авторизован ли пользователь, то ни с какого реферера неавторизованный пользователь ничего не сделает
1. Человек авторизован на каком-нибудь сервисе service.com
Разберёмся по порядку. Я ещё раз повторю. Сценарий подразумевает, что человек уже авторизован. Авторизация допустим хранится в браузере в качестве сессионной куки. Пусть эта кука называется session_kuk.

Это подразумевает (хотя я могу конечно ошибаться, но меня тогда поправят, надеюсь) что при любом запросе из этого конкретного экземпляра браузера (который как мы помним хранит куку) на хост service.com эта кука будет отослана.

Значение этой отосланной куки трудно переоценить. Она явно и недвусмысленно говорит, о том, что пользователь _авторизован_ в системе.
--------------------
Дальше - больше.
3. Страница hack.net формирует POST запрос согласно логике приложения service.com (с помощью hidden полей и JS самбита формы) и отправляет его на service.com.
Сабмит формы выполняется автоматически, понимаешь? С помощью допустим JavaScript.

Теперь возвращаемся к твоей чудестной гостевухе. Мальчик Петя читает гостевуху. Или нет. Пусть это будет лучше форум. Мальчик Петя читает форум. Он авторизован.
Хакер Вася хочет порезвиться. Он пишет ссылку на свой сайт
и там стоит что-нибудь типа
<form method='POST' action='http://service.com/phorum?thread=12345'>
<input type='hidden' name='new_message' value='Вы все тут [вырезано цезурой]!!!'>
</form>
<script language='Javascript'>
....
код автосабмита
....
</script>
Петя, нажав на эту ссылку получает бан. Почему? Потому что "все не думают, что" они [вырезано цензурой]. А сообщение было отправлено от его имени. И вот - Петя в шоке, Вася утробно хохочет, администрация форума получает письма, потому что в кузнице не было гвоздя, а именно - кто-то умный не проверил HTTP_REFERER.
-----------------------------------------------------------------------------------

Но это не аргументы. Это просто мои размышления по поводу.
Поэтому,
crocodile2u, если ты дочитал до этого места - имей себе ввиду, что проверка HTTP_REFFERER защищает не сервер от взлома, а пользователя этого сервера.
 

ForJest

- свежая кровь
Всем сомневающимся предлагается эта ссылка
Здесь описан аналогичный случай и довольно подробно :D
{----}
По ссылке совершалось всё то, что описано в сценарии. Встречающиеся в дальнейшем сообщения вида
"Я верю, что нужно проверять HTTP_REFERER и ставить себе Kerio Firewall, чтобы не подстрять на тех серверах, где этого не делают! " это те сообщения, которые были совершены без участия авторов.
ForJest, а кто мешает хакеру Васе, вместо банальной подмены action формы, сформировать нужный POST-запрос на сервере - хотя бы с помощью PHP и CURL? И подставить туда абсолютно чистый перед любой проверкой REFERER, столь любезно предоставленный ему мальчиком Петей?
А вот об этом ты скажешь мне, когда нажмёшь на ссылку и немного подумаешь.
 

ForJest

- свежая кровь
IL78
Объясняю популярно. Видишь ссылки для управления форумом? Всякие настройки, письмо админу, СМ. НЕПРОЧТЕННОЕ и т.п.?
Вот - абстрагируйся от того, где они находятся на странице.
Элементу управления без разницы, где находится - в трэде или вокруг. Я просто добавляю свою функциональность и пользуюсь скриптами сервера, вот и всё. Серверу всё равно, откуда пришли данные - главное, что их прислал авторизованный пользователь - так понятно?. Данные отсылает браузер пользователя. Я только помогаю пользователю отослать те данные, которые я(не пользователь) хочу отослать. Вот и всё

-~{}~ 09.08.04 14:48:

Таким образом получается, что сервер думает, что данные прислал пользователь, а на самом деле их прислал браузер пользователя. И прислал он те данные, которые решил отослать я - простой русский хаккер Вася.
 

confguru

ExAdmin
Команда форума
У меня грузится пустая страница с жаба скриптом..
А что там должно быть?
 

Romantik

TeaM PHPClub
Я верю, что нужно проверять HTTP_REFERER и ставить себе Kerio Firewall, чтобы не подстрять на тех серверах, где этого не делают!

-~{}~ 09.08.04 16:28:

=)
 

ForJest

- свежая кровь
...который можно имитировать серверным скриптом, не так ли? Причем необязательные заголовки, к числу которых относится HTTP_REFERER, можно подставить любые. Таким образом сервер подумает, что данные прислал браузер пользователя, а на деле их прислал сервер хакера Васи.
А кто пустит хаккера Васю за компьютер пользователя? Может быть Васе далеко ехать и довольно удобно сидеть за своей тачкой, не находишь? :)
 

Romantik

TeaM PHPClub
Я верю, что нужно проверять HTTP_REFERER и ставить себе Kerio Firewall, чтобы не подстрять на тех серверах, где этого не делают!
 

ForJest

- свежая кровь
IL78
У тебя ошибка в том, что ты думаешь, что в моём скрипте что-то делается. А там чистый html.
 

McLay

PHP5 BetaTeam
Я верю, что нужно проверять HTTP_REFERER и ставить себе Kerio Firewall, чтобы не подстрять на тех серверах, где этого не делают! ForJest - я с тобой, да! Пусть разум будет посрамлён,.. ДИСКОТЕКА! :););D

-~{}~ 09.08.04 16:25:

Ловко :)
 

ForJest

- свежая кровь
Фанат
Рефер как раз панацея. Мне уже правда надоело об этом говорить - никто не хочет верить :)
--------------

патч для
PHP:
if ((isset($_POST) || isset($_GET)) && isset($_SERVER['HTTP_REFERER']) 
&& strlen($_SERVER['HTTP_REFERER'])) 
{ 
     $refer = parse_url($_SERVER['HTTP_REFERER']); 
     if (FALSE === strpos($refer['host'], $_SERVER['SERVER_NAME']) and 
         FALSE === strpos($refer['host'], $_SERVER['HTTP_HOST'])) 
     { 
          die('Invalid ref!'); 
     } 
}
проверено и работает.
Скрипты для проверки:
service.com/test_ref.php
PHP:
<?php
session_start();
if (isset($_GET['user']))
{
     $_SESSION['user'] = $_GET['user'];
     header('Location: '.$_SERVER['SCRIPT_NAME']);
}
if (!isset($_SESSION['user']))
{
     die('No autorization');
}
if ((isset($_POST) || isset($_GET)) && isset($_SERVER['HTTP_REFERER']) 
&& strlen($_SERVER['HTTP_REFERER']))
{
     $refer = parse_url($_SERVER['HTTP_REFERER']);
     if (FALSE === strpos($refer['host'], $_SERVER['SERVER_NAME']) and
         FALSE === strpos($refer['host'], $_SERVER['HTTP_HOST']))
     {
          die('Invalid ref!');
     }
}
if (isset($_POST['message']))
{
     echo $_SESSION['user'].' said: '.$_POST['message'];
}
?>
<a href='http://test/ref.php'>Click Here!</a>
index.php
PHP:
<a href='http://service.com/test_ref.php'>Test</test>
hack.net
PHP:
<form method='POST' action='http://service.com/ref_test.php'>
<input type='hidden' name='message' value='Fucking HTTP_REFERER!'>
</form>
<script language='JavaScript'>
document.forms[0].submit();
</script>
-~{}~ 09.08.04 15:42:

KR
Если что-то режет рефер оно обычно режет и куки при редиректе. У меня при включенном Kerio вылетает No autorization.
Если же нечто будет резать рефер и не резать куку - нафих такое нечто нужно?
 

McLay

PHP5 BetaTeam
Фанат
Проверять рефер, если я правильно понял, имеет смысл только когда авторизация происходит с помощью кук. У кого режет рефер могут пользоваться сессиями.
 

ForJest

- свежая кровь
Ладно. Короче этим трэдом я надеялся доказать, что проверка HTTP_REFERER является средством защиты пользователя от надстроек над приложением которые производить злоумышленник. При некоторых условиях это решение не работает. Но это не повод его не применять.
-------------------
Что я ещё могу сказать? ПРОВЕРЯЙТЕ HTTP_REFERER
 

ForJest

- свежая кровь
Кстати решение есть. Но не очень простое в плане апдейта скриптов. В форме сабмита должен стоять
<input type='hidden' name='PHPSESSID' value='<?echo session_id?>'>
И всё. Если они совпадают - постим. Если нет - гуляй.

-~{}~ 09.08.04 16:07:

Дальше - больше. Представим себе ситуацию, когда у пользователя отключены куки. Соответственно по HTTP_REFERER злоумышленник узнаёт session_id. И подставляет его и в такое решение :).
 

McLay

PHP5 BetaTeam
Автор оригинала: Фанат чтобы совсем уж в степь тему не уводить
И без тебя увели :)

ForJest
Дальше - больше. Представим себе ситуацию, когда у пользователя отключены куки. Соответственно по HTTP_REFERER злоумышленник узнаёт session_id. И подставляет его и в такое решение
Для форм можно использовать отдельное id, например случайное число, записав его в сессию.
 

ForJest

- свежая кровь
Ещё можно интересное решение. В таком же
<input type='hidden' name='post_certificate' value='что-то'>
На сервере сохраняется сертификат для поста. Допустим это хранится прямо в сессии - номер текущего сертификата. Или набор таких сертификатов :) Случайный чисел. После поста он проверяется и уничтожается.
----------
Проблема только в том, что если допустим quck form как здесь то этих чисел нагенериться очень много. По сути дела для каждой открытой страницы нужно подобную последовательность хранить, что вредным образом скажется на производительности системы.
-----------
Ещё можно сделать двухступенчатый пост. Т.е. с preview. Юзер сначала постит, потом подтверждает, что именно это он и хотел сделать. Но это плохо скажется на юзере и сделает систему более громоздкой :).
------------
Но такое решение можно применять по результатам тестов самой системы.
Т.е. - при входе система проверяет себя на дырявость с помощью дружественного хоста, после чего включает ту или иную меру защиты. Всё - пока больше идей нету :)
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху