|
|
|
| Народ! Посмотрите на мой скрипт авторизации с помощью сессий, может кто найдет дыру в авторизации.
Файл login.php для входа в систему
<?php
Include ("include/settings.php");
$server_name = $HTTP_SERVER_VARS['SERVER_NAME'];
$http_referer = $HTTP_SERVER_VARS['HTTP_REFERER'];
$login = $HTTP_POST_VARS['login'];
$password = $HTTP_POST_VARS['password'];
print "<br>".$server_name;
print "<br>".$http_referer;
print "<br>".$db_hostname;
print "<br>".$db_username;
print "<br>".$db_password;
if (eregi("$server_name",$http_referer)){
if (($submit) and (ereg("[A-Za-z0-9]",$login)) and (ereg("[A-Za-z0-9]",$password))){
if (mysql_connect($db_hostname,$db_username,$db_password))
{
if (!mysql_select_db($db_tablename))
{
echo "Error select MySQL DB";
exit;
}
$query = "SELECT DISTINCT Username, Status, Maillist, Fio FROM ".$prifex."mail_managers WHERE Username = '".$login."' and Password = '".md5($password)."';";
$r = mysql_query($query);
mysql_close();
if ($r)
{
$id = md5(rand(10000,99999));
session_start();
$HTTP_SESSION_VARS["auth"] = 1;
$HTTP_SESSION_VARS["status"] = mysql_result($r,0,1);
$HTTP_SESSION_VARS["maillist"] = mysql_result($r,0,2);
header("Location: admin.php");
exit;
}
}
else
{
header("Location: http://".$http_referer);
}
}
else
{
header("Location: http://".$http_referer);
}
}
else
{
print "<br>"."ref";
header("Location: http://".$server_name);
}
?>
|
Файл auth.php для проверки прошел ли пользователь авторизацию.
<?php
session_start();
$auth = $HTTP_SESSION_VARS["auth"];
$status = $HTTP_SESSION_VARS["status"];
$maillist = $HTTP_SESSION_VARS["maillist"];
if ($auth != 1){
unset($HTTP_SESSION_VARS["auth"]);
unset($HTTP_SESSION_VARS["status"]);
unset($HTTP_SESSION_VARS["maillist"]);
session_destroy();
header("Location: ".dirname($HTTP_SERVER_VARS['PATH_INFO']));
exit;
}
?>
|
| |
|
|
|
|
|
|
|
для: Staaas
(02.01.2005 в 13:37)
| | 1) В SQL запросе:
<?php
$query = "SELECT DISTINCT Username, Status, Maillist, Fio FROM ".$prifex."mail_managers WHERE Username = '".$login."' and Password = '".md5($password)."';";
?>
|
имеется переменная $prifex - она в settings.php определяется? Тогда следует проследить чтобы она была всегда инициирована.
2) Можно авторизоваться с другого хоста, создав на нём форму и указав в качестве action полный сетевой путь к login.php. Для исключения автоподбора пароля с друго хоста в форме следует разместить скрытое поле поместив туда идентификатор сессии, а в login.php проверить на соответствие текущего идентификатора и переданного методом POST.
3) Что произойдёт если в строке запроса просто набрать admin.php, минуя login.php?
4) Стоп... а у вас неправильно автризация происходит - попробуйте набрать неправильное имя и пароль - скрипт должен вас пустить. mysql_query($query) всегда возвращает дескриптор запроса, если SQL-запрос верен и возвращает FALSE только в случае ошибки в синтаксисе. Следует проверять не дескриптор, возвращённый mysql_query(), а число строк при помощи функции mysql_num_rows($r).
http://www.softtime.ru/dic/id_dic=122&id_group=2 | |
|
|
|
|
|
|
|
для: cheops
(02.01.2005 в 14:03)
| | Если в строке запроса набрать admin.php, то скрипт auth.php (код приведен выше)проверяет сначала прошел ли пользователь авторизацию, если нет, то перенаправляет на страницу ввода пароля.
Перемення $prifex указывается в settings.php.
По поводу подбора пароля с другого хоста, то перед началом проверки имя пользователя проверяется с какого хоста пришел запрос. | |
|
|
|
|
|
|
|
для: Staaas
(02.01.2005 в 14:50)
| | Мне ничего не помешает подставить нужный реферер при запросе, поэтому все же нужно сделать проверку, так как напи сали выше в ответе. | |
|
|
|
|
|
|
|
для: XPraptor
(05.01.2005 в 10:49)
| | Просветите меня- header() в файле login.php этого примера -служебная функция PHP или самодельная? | |
|
|
|
|
|
|
|
для: coloboc66
(05.01.2005 в 11:20)
| | Это функция PHP. С ее помощью можно отправлять HTTP-заголовки. | |
|
|
|
|
|
|
|
для: glsv (Дизайнер)
(05.01.2005 в 11:48)
| | cheops писал:
2) Можно авторизоваться с другого хоста, создав на нём форму и указав в качестве action полный сетевой путь к login.php. Для исключения автоподбора пароля с друго хоста в форме следует разместить скрытое поле поместив туда идентификатор сессии, а в login.php проверить на соответствие текущего идентификатора и переданного методом POST.
[1] А id сессии в скрытое поле как правильно поместить?так:
<?php
<input type="hidden" name="id" value=" <?php print session_id();?>">
?>
|
или так:
<?php
<input type="hidden" name="id" value=" <?php session_id();?>">
?>
|
<?php
if(session_id()!==$id){/*или сессия не запущена чтоб проверять id? тогда где её стартовать если это форма авторизации?сразу при обращении к старице?*/
session_unset();
session_destroy();
Header("location:index.php");
exit;
}
else{........}
?>
|
?????
[2]Влияет ли как то на безопасность размещение формы
и её обработчика в одном файле? | |
|
|
|
|
|
|
|
для: method
(30.06.2005 в 19:35)
| | 1) Следует использовать первый вариант
<?php
<input type="hidden" name="id" value=" <?php print session_id();?>">
?>
|
так как функция session_id() возвращает строку и не выводит значение в окно браузера.
2) Размещение формы и обработчика в одном файле на безопасность не влияет (если, конечно о безопасности позаботиться :). | |
|
|
|
|
|
|
|
для: cheops
(01.07.2005 в 00:41)
| | ведь можно на другом хосте в значении скрытого поля прописать
значение сессии посмотрев его (в опере например управление куками).....
или это ни чего не даст?
ЗЫ:посмотрите пожалуста коментарий в коде в верхнем моём посте... | |
|
|
|
|
|
|
|
для: method
(01.07.2005 в 06:01)
| | Да, это так, но время жизни сессии ограничено и ущерб будет не таким большим, как если бы форма была просто открыта.
Там где происходит обращение к сессии её следует иниициировать размещая функцию sesion_start() до любого вывода в окно браузера - лучше в самой первой строке.
<?php
sesion_start();
// Код
if(session_id()!==$id){/*или сессия не запущена чтоб проверять id? тогда где её стартовать если это форма авторизации?сразу при обращении к старице?*/
session_unset();
session_destroy();
Header("location:index.php");
exit;
}
else{........}
?>
|
| |
|
|
|
|
|
|
|
для: cheops
(01.07.2005 в 09:15)
| | cheops
Да, это так, но время жизни сессии ограничено и ущерб будет не таким большим, как если бы форма была просто открыта.
но ведь данные же будут отправлены ? значит если это форма чата где поле
text readonly чужак который всё это проварачивает может обойти это readonly?
так получается? | |
|
|
|
|
|
|
|
для: method
(01.07.2005 в 11:52)
| | а может скрытому полю присвоить ip сервера, и проверять таким образом,
или чё то меня понесло вроде...=)
возможно ли такое?
если да то подскажите функцию которая определяет ip сервера .... | |
|
|
|
|
|
|
|
для: method
(01.07.2005 в 12:03)
| | ндя....точно я прогнал.....
тогда может как нибудь сравнивать и то и другое относительно
scriptname и его место расположения?
PS сейчас озадачен безопасностью приложения
которое не будет считаться доделаным пока не буду
уверен в его надёжной защите.... | |
|
|
|
|
автор: Гость.. (01.07.2005 в 14:45) |
|
|
для: method
(01.07.2005 в 12:29)
| | У меня была подобная проблема - как обезопасить форму от бутафорса, выход получился на мой взгляд довольно удачный... в БД создаешь дополнительный столбец, в котором указываешь колчичество неудачных попыток, когда неудачных попыток (за 10 минут) становится болше 3-х просто выводится надпись : отдохните 5-ть минут... после чего значение неудачных попыток войти просто обнуляется... на мой взгляд бутафорс в таком случае уже не чем не поможет.... | |
|
|
|
|
|
|
|
для: Гость..
(01.07.2005 в 14:45)
| | Из статьи Владислава Путяка:
Однако я бы посоветовал не применять блокировку IP - ее можно элементарно обойти, а многие пользователи прокси серверов могут страдать из-за нее. Гораздо разумнее применить задержку авторизации. Т.е. непосредственно перед проверкой корректности логина и пароля делаем задержку, скажем на 1 секунду. Пользователи ее скорее всего даже не заметят, а вот у хакеров скорость перебора упадет ниже 1 комбинации в секунду, что фактически полностью исключает возможность перебора пароля даже по специальному словарю. Осуществить задержку можно так:
<?php sleep(1); //задержка на 1 секунду?>
|
Вот такие пироги....
А у меня чуть другая задача,пресечь отправку из форм
с других хостов, читай посты выше...
PS cheops вы где? | |
|
|
|
|
|
|
|
для: method
(01.07.2005 в 15:07)
| | IP-адрес нам ничего не даст... так как всегда будет подставляться адрес посетителя, а какая форма используется, с этого хоста или другого проверить нельзя, так как посетитель отправляет данные тоже со своего хоста. Введите бан по IP-адресу и особенно отличившимся закрывайте доступ к чату на некоторое время. | |
|
|
|
|
|
|
|
для: cheops
(01.07.2005 в 20:08)
| | тогда может как нибудь сравнивать чё нить с чем нить относительно
scriptname и его место расположения?
вот такое даст гарантию:
<?php <form action="<?=$_SERVER["SCRIPT_NAME"]?>" method=POST>
?>
|
??? | |
|
|
|
|
|
|
|
для: method
(02.07.2005 в 06:57)
| | Нет, так как у злоумышленика будет своя собственная копия формы, в которую он подствит те, значения которые захочет, или он вообще не будет прибегать к HTML-форме и сделает всё через сокеты, напрямую обращаясь к обработчику. | |
|
|
|
|
|
|
|
для: cheops
(02.07.2005 в 11:37)
| | cheops скажите не томите если
знаете что нить кроме того что вы уже
посоветовали, т.е.
<?php
<input type="hidden" name="id" value=" <?php print session_id();?>">
?>
|
| |
|
|
|
|
|
|
|
для: method
(02.07.2005 в 13:45)
| | Поставить проверку на то, с какого сайта пришли данные... | |
|
|
|
|
|
|
|
для: TrunK
(02.07.2005 в 14:48)
| | привидите пример.... | |
|
|
|
|
|
|
|
для: TrunK
(02.07.2005 в 14:48)
| | Это как раз и решается при помощи прошивки сессии - помещение в скрытое поле уникальное значение, которое знает только сайт. method-у этого не достаточно.
PS Проблема в том, что HTML-форма на самом деле находится не на сервере - она отправляется клиенту и клиент, заполнив её отправляет данные на сервер. Поэтому данные всегда идут с клиентской машины. Поэтому можно поставить робот, который со скоростью 20 сообщений в минуту 24 часа в сутки будет постить сообщения... Вот, кстати, ещё одно решение - проверять сколько времени прошло с момента последнего помещения сообщения с данной сессии - если менее 5 секунд, не помещать повторные сообщения. Если таких попыток будет больше 10 - блокировать размещение сообщений с данной сессии. | |
|
|
|
|
|
|
|
для: method
(02.07.2005 в 13:45)
| | Нет другой автоматической проверки у вас не выйдет, не зависимо от того, знаю я это или нет :))) так как это не позволяет сам протокол HTTP - он не сессионный. Это означает, что сервер, отправившего HTML-форму клиенту, дальнейшая её судьба не волнует, с какого адреса придёт ответ, получал ли этот клиент перед этим форму, сокет ли обращается или какой другой зверь, Web-серверу совершенно наплевать. Именно для решения проблем, возникающих в этом случае были введены cookie и сессии. Ничего лучшего на настоящий момент нет.
Вы можете поставить дополнительную проверку на USER_AGENT, но USER_AGENT легко подделать и вряд ли это остановит злоумышленика. Возможно слабым утешением вам будет тот факт, что за всё время существование нашего форума случаев автофлуда не было, хотя его посещает большое число посетителей подавляющее большинство из которых неслабо разбирается в PHP. | |
|
|
|
|
|
|
|
для: cheops
(02.07.2005 в 17:13)
| | cheops как всегда премного благодарен за оч хороший ответ =)
ЗЫ:хотя мне показалось что раньше чем понедельник я его не услышу,
потому сгонял на пхп клаб пришлось региться и создавать такую ж тему.......
ну да ладно лишним не будет.....
спасибо! | |
|
|
|