Опять о авторизации
Я написал скрипт авторизации пользователя. Работает он вроде бы нормально,
но хотелось бы узнать насколько правильна моя система авторизации (плюсы и минусы).
А если есть возможность объяснить в чем моя ошибка и как можно улучшить.
Я сдышал про register_globals, там есть свои нюансы(у меня кстати в on выставлено)
Структура:
ФАЙЛ CONFIG.PHP
function _permission()
{
global $ok_user;
if(!session_is_registered("ok_user"))
{
login('');
exit();
}
}
function Login($message)
{
?>
<body onLoad="document.forms.sdloginform.'.$focus.'.focus()">
<form name="form" id="form1" method="post" action="login.php">
<table>
<tr>
<td>
<? if(strlen($message) > 0)
{ echo $message; }
?>
</td>
</tr>
<tr>
<td>LOGIN<input name="username" type="text">
</td>
</tr>
<tr>
<td>PASSWD<input name="password" type="password"></td>
</tr>
<tr>
<td><input type="submit" name="login" value="Submit"></td>
</tr>
</table>
</form>
<? }
ФАЙЛ LOGIN.PHP
<?
include('config.php');
session_start();
if($logout==1)
{
session_unregister("ok_user");
session_destroy();
}
if(isset($_POST['login']))
{
$loginusername = strip_tags(trim($_POST['username']));
$loginpassword = strip_tags(trim($_POST['password']));
$sql="select user from users where user='$loginusername'";
$res=db_select($sql);
$n=mysql_num_rows($res);
if($n==0)
{
login('Неправильный логин.');
exit();
}
else
{
$sql="select pass from users where user='$loginusername'";
$res=db_select($sql);
$pass=mysql_result($res, 'pass');
if($pass != md5($loginpassword))
{
LogIn('Неправильный пароль.');
}
else
{
$ok_user=$loginusername;
session_register("ok_user");
Header("Location: index.php");
}
}
}
else
{
login('');
exit();
}
А потом в каждом файле который защищаю авторизацией пишу:
include('config.php');
session_start();
_permission();
?>
$loginusername = strip_tags(trim($_POST['username']));
$loginpassword = strip_tags(trim($_POST['password']));
$sql="select user from users where user='$loginusername'";
Это дыра. Ты не избавляешся от кавычек, что позволяет провести SQl-инжектинг и ты убираешь только теги забывая про & , что позволяет провести CSS.
$res=db_select($sql);
$n=mysql_num_rows($res);
Это меня плющит или тебя? И мы оба видим одно и тоже?
P.S. Может адресок кинешь, где оно у тебя лежит :D
А потом в каждом файле который защищаю авторизацией пишу:
include('config.php');
session_start();
_permission();
?>
Минус такого подхода в том что если я знаю твою переменную ok_user то зарегистрировав где нибудь
$ok_user="какая то ерунда а не логин и не пароль"
Легко пройду к защищенным страницам.
Избежать этого можно запомнив в сессии логин и пароль и на каждой страничке проверять с БД.
Плюс: просто и быстрее чем БД каждый раз пользовать. и кроме того попробуй еще имя переменной сессии стырить, не каждый додумает как оно. Да и кроме того многим ли надо на хомпейдже гостивуху или еще что ломать?
Это меня плющит или тебя? И мы оба видим одно и тоже?
P.S. Может адресок кинешь, где оно у тебя лежит :D
А вчем проблема то? Я что-то не понимаю? Обьясни(я пока новичек)
В первые слышу .
Это значит что юзер может выполнять запросы к моей базе через сайт?
Здесь вообще ничего не понял
В первые слышу .
Это значит что юзер может выполнять запросы к моей базе через сайт?
Здесь вообще ничего не понял
Причем тут выполнять запросы к товей базе?*
Как ты проверяешь что юзер может находиться на этой страничке???
if(!session_is_registered("ok_user"))
следовательно если эта переменная зарегистрирована не важно с каким значениме то можно эту страницу смотреть.
А что б такого небыло надо проверить что
ok_user=login для этого надо сделать запрос в бд и сравнить значение логина переменной сессии с значением в БД
пример SQL-inject( inject-вставлять,вводить и т.д.(en) )
1.
select ... where login=$login;
если $login="1 or 1=1"
то sql-сервер получит такой запрос:
select ... where login=1 or 1=1;
это самое простое можно вообще целые отдельны запросы делать
и если прав хватит то можно вообще базу увести
ВСЕГДА ограничивать ковычками вводимы значения:
select ... where login='$login';
select ... where login='1 or 1=1';
2.
select ... where login='$login';
если $login="1' or 1=1"
то sql-сервер получит такой запрос:
select ... where login='1' or 1=1;
ВСЕГДА бить,экранировать, конвертить и т.д. твои рабочие ковычки(здесь ') и '\' да и вообще все что не альфанумерек лучьше экранировать , php если я не ошибаюсь это делает сам... но лучьше не полагатся на это так как опционально(т.е. не обязательно)
Причем тут выполнять запросы к товей базе?*
Как ты проверяешь что юзер может находиться на этой страничке???
if(!session_is_registered("ok_user"))
следовательно если эта переменная зарегистрирована не важно с каким значениме то можно эту страницу смотреть.
хм...
поправь меня если я ошибаюсь но переменная ok_user определенна только когда прошла удачная авторизация, и в чем тут уязвимость я не понял...
хм...
поправь меня если я ошибаюсь но переменная ok_user определенна только когда прошла удачная авторизация, и в чем тут уязвимость я не понял...
Ну смотри, я у себя на домашнем сервере запускаю скприпт
<?php
session_register('ok_oser');
ok_user='не логин не пароль';
?>
Дальше захожу на твою страничку а там проверка
if(!session_is_registered("ok_user"))
{
login('');
exit();
}
Значит если переменная сессии зарегистрирована то значит это объявление игнорируется, и значит выводится та часть страници которую ты хотел защитить.
А как на счет magic_quotes? просто и без запар?
Ну смотри, я у себя на домашнем сервере запускаю скприпт ...
Дальше захожу на твою страничку а там проверка
и значит выводится та часть страници которую ты хотел защитить.
Ага, Alone недавно у себя на серваке телепатор пропатчил, только где гарантия что его телепатор совместим с твоим телепатором?
magic_quotes- ересь!
А вообще, по поводу инжекта с логином и паролем, я вот запрещаю в логине и пассе юзать что-либо, акромя альфанумерикоф. Думаецц, кроме как пароля да логина, нигде у него юзер большего ничего руками не вбивает.. Так что этого хватило бы.. Или хз, может туплю (утрення белка?), я еще не проснулся=))
хм.. или высылай версию своего телепатора :)
похоже что товарищ Yuri Koslow не понимает что такое сессия и где хронятся переменные сессии... очень советую закрыть этот пробел в знаниях...
хм.. или высылай версию своего телепатора :)
Был бы признателен если бы свою критику вы подкрепили ссылками, на русском языке.
И как на счет если ввести в строку запроса ?
Session%5Bok_user%5D=1
И как на счет если ввести в строку запроса ?
Session%5Bok_user%5D=1
Session :: Array
array(1) { ["ok_user"]=> string(1) "1" }
ты не поверишь, но он регистрирует массив Session в массиве _GET. Поразительно, но факт.
Возможно ты спутал это дело с общими сессиями на одном хостинге - тогда да, сценарий чем-то похож на то что ты описал вначале. Ссылками не обрадую, посмотри на phpclub.ru . На doks.gorodok.net книжка по php лежала, там тоже что - то про сессии было. В общем ищите и да пребудет с вами Сила...
Не обижайся Кослов (Не над изгаляцца над фамилиями, даж не знаю как написать) =) Эт не критика, а так, маленькое "хы". На этом же вот сайте, codenet.ru =), лежат и учебники и все что нужно.. Если найду что полезное в букмарках скину, но это вообще все сакс, надо читать бумажную литру, там все объяснят гораздо подробней, чем в манах=) И доступней=) Если книжка кнечно хорошая=)
Ну для начала я не обиделся.
Т.к. видимо не достаточно хорошо представляю как клиет взаимодействует с свервером, и что такое куки и как они родятся.
По поводу книжек, был бы признателен если б рекомендовали книги.
ЗЫ: Например в руководстве "Освой самостоятельно PHP4" Мет Зандстра я нашел что сессии хронятся в куках, или в url -> SID, и там обсуждалась проблемма подобной авторизации. Но скажем Люк Веллинг и Лора Томсон "Разработка WEB приложений с помощью PHP и MySQL" рекомендуют именно такой подход к авторизации.
я нашел что сессии хронятся в куках, или в url -> SID, и там обсуждалась проблемма подобной авторизации. Но скажем Люк Веллинг и Лора Томсон "Разработка WEB приложений с помощью PHP и MySQL" рекомендуют именно такой подход к авторизации.
Только не сессии, а индентификаторы сессий... А сама сессия хранится на сервере и чтобы их изменить, тебе надо либо иметь sid, либо права админа :) Так что ничего страшного в
if(!session_is_registered("ok_user")) - нету...
Хотя я бы написал if($_SESSION["ok_user"]) - так читается лучше.
$sql="select user from users where user='$loginusername'";
$res=db_select($sql);
$n=mysql_num_rows($res);
if($n==0)
{
login('Неправильный логин.');
exit();
}
else
{
$sql="select pass from users where user='$loginusername'";
$res=db_select($sql);
$pass=mysql_result($res, 'pass');
if($pass != md5($loginpassword))
{
LogIn('Неправильный пароль.');
}
To Nicca:
А вот здесь не ясно - зачем делать 2 выборки, когда достаточно 1? Сразу выбираешь пароль и проверяешь на валидность, если ничего не выбрано - значит неправильный логин.
1. Вы будете смеятся но то значит "у себя на серваке телепатор пропатчил"?
2. chigevara! А что плохого в
$res=db_select($sql);
$n=mysql_num_rows($res);
Я так и не монял. Объясни пожалуйста!
3. У меня на серваке magic_quotes=on и потому когда я пишу
login='badlogin' or 1=1 то запрос получается: select pass from users where login='badlogin\' or 1=1'
получается что здесь никак через подстановку не получится пройти авторизацию? И можна ли обойти magic_quotes?
4.Прочитал здесь о SQL-inject и стало страшно за свои скрипты. Получается через адрессную строку в броузере можно что угодно подставлять. Если запрос идет на выборку данных(например скрипт новостей, каталог...), то как нужно обрабатывать переменные которые подставляются в запрос?
news.php?id=23&date=2004-07-12
Например: select * from news where parent=$id and date_in='$date'
И вообще возможно ли что-то плохое сделать если идет запрос на выборку данных? Можете привести несколько примеров "плохих" запросов?
А как можно взламать гостевую? Дело в том что я совсем не проверяю входящих переменных(хотя в гостевой всего 1 запрос insert)
1. Вы будете смеятся но то значит "у себя на серваке телепатор пропатчил"?
Я в истерике :D Телепатор - это такой телепатический модуль, позволяет общаться сервакам и людям без каких бы то ни было средств коммуникаций. Но в связи с разнородностью операционок на серваках и разнобоем в мышлении людей, время от времени телепаторы надо патчить, что бы они понимали все новомодные примочки, которые плодятся день ото дня.
2. chigevara! А что плохого в
$res=db_select($sql);
$n=mysql_num_rows($res);
Я так и не монял. Объясни пожалуйста!
во первых mysql_select_db(). Во вторых ты выбору базы передаешь строку запроса а не имя базы.
Если меня не плющит, последовательность действий выглядит так:
mysql_connect();
mysql_select_db();
mysql_query();
mysql_result | mysql_fetch_array | etc
mysql_close();
3. У меня на серваке magic_quotes=on
А завтра ты поменяешь хостера, у него будет off, но про magic_quotes ты уже забудешь, а послезавтра в гости к тебе загляну я и тебе будет очень обидно.
magic_quotes И можна ли обойти magic_quotes?
Обойти кому?
4.Прочитал здесь о SQL-inject и стало страшно за свои скрипты.
:D
Еще как!
Оставляй только то, что ты ждешь, если цифры, то только цифры, если буквы, то только буквы.
Если от тебя зависит, то старайся, что бы это были только цифры, и обрабатывать легче и спать спокойнее. Почитай про regex-ы, они тебе сильно облегчат жизнь.
И вообще возможно ли что-то плохое сделать если идет запрос на выборку данных?
Если я с помощью твоего кривого запроса получаю права админа на твоем сайте, то ничего хорошего в этом для тебя нет. Примеры плохих запросов можешь посмотреть в Сети, там народ пишет чуть более лучше меня разбирающийся в хаке. Набей SQL инжектинг в поисковике. Последняя уязвимость phpBB кстати тоже была с этим связана, можешь посмотреть.
А как можно взламать гостевую? Дело в том что я совсем не проверяю входящих переменных(хотя в гостевой всего 1 запрос insert)
Ты экстремал. Представь что будет, если отправить сообщение с тегами html, кодом js. Если я знаю какие ты шаблоны используешь при выводе то возможно смогу посмотреть значение каких нибудь переменных. В конце концов просто вставить в базу что нибудь не то куда нибудь не туда. Сам запрос покажи.
P.S. Туплю. db_select - это твоя функция?
пральна говорит, юзай в "полях" доступных пользователю лишь те символы, ктьорые действительно необходимы.. А-то ведь мороки не оберешься..)
И еще от меня, следи за своим стилем кодинга:) Придумай свой, или юзай чужой, лишь бы граммотный.. Не перевариваю $bz = "select * from `$table`"; Эт че? Обыкновенно, лучше (ну мне так больше нравицца:) юзать конструкцию $bz = sprintf('select * from `%s`',$table). Эт в perl, я не полклонник php:) Не поверишь, но так удобней, гораздо.. Надо только привыкнуть:))
А завтра ты поменяешь хостера, у него будет off, но про magic_quotes ты уже забудешь, а послезавтра в гости к тебе загляну я и тебе будет очень обидно.
Если можно то с этого места по подробней.
А как на счет set_magic_quotes_...
Или в корень php.ini?
Вполне возможно что гуру то и не надо оно, а лично мне оч. Хорошо помогает магическая кавычка, и при смене сервера ни каких проблем не возникало