Новичку полезно



Безопасность при авторизации

Теги: авторизация, безопасность

Если вы внимательно читали все предыдущие статьи, то у вас уже должно быть достаточно знаний чтобы написать какой нить не сложный проект. Единственное что у вас скорее всего будет недостаточно – опыта. В частности, как у новичков, так и у более продвинутых программистов часто бывают вопросы о том, как реализовать систему registration – login – remind password. Конечно, на эту тему можно спорить сколько угодно долго, но я выскажу лишь своё мнение, и не настаиваю что это единственное правильное, хотя коды которые я видел по долгу службы заставляли меня посмеяться. Я не знаю правильно ли я делаю что публикую эту статью раньше чем я завёл разговор о базах данных, однако с безопасностью баз данных будет другой разговор. Сейчас будем считать что все данные сайта храниться только в файлах.

Во первых, в большинстве сайтов пользователь сам задаёт себе пароль, однако, особо – прогрессивные сайты (в плане безопасности) дают пользователю пароль состоящий из всякой гадости. ИМХО – пользователь сам должен обеспечивать себе безопасность, и если пользователь хочет, пускай сам придумывает себе пароли длинные, если он их придумывает сам, ему легче запомнить. Например, я знаю народ которые использует как пароли серийники к программам. Я например, использую сочетание букв и цифр, однако эти сочетания связанны именно со мной, и по этому мне не сложно это запомнить. Единственно где это может быть оправданно – если юзеру могут дать, например, права админа, и тогда при взломе его акаунта не только он может понести убытки, но и сайт. Один из способов генерации случайного пароля (хотя я не считаю его наилучшим, однако я его встретил в одном огромном проекте):

function generate_password (){
 $password = substr (md5 (mt_rand ()), 0, 8);
 return $password;
}

Прототип функции mt_rand: 
int mt_rand ( [int min, int max] )
Однако если её вызвать без параметров, то она сгенерит число от 0 до RAND_MAX. Теперь одна из самых важных функций, которую мы будем использовать и далее – это md5() Она генерит md5 хеш (если кто не знает что такое хеш – в гугл пожалусто). Недавно пошли слухи, что этот алгоритм шифрования больше не являеться защищённым, и его можно взломать буквально за час. На это я могу ответить только одно – ничего не совершенно. Однако, из моих знакомых, которые намеривались за 20 минут взломать мой хеш, пока ещё до сих пор никто его не поломал, так что то что алгоритм md5 всё ещё испльзуют многие сайты вполне оправданно, однако всё же лучше делать так чтобы хеши были недоступны кому – попало.
Итак, вернёмся к регистрации. Осталось сохранить пароль, и незабыть сообщить его пользователю. Например, если форма регистрации была:


Login: Email:

  Тогда, сценарий обработки будет что то типо такого (saveuser – функция для сохранения юзера, например в фаил):

$pass = generate_password();
If (saveuser($_POST['login'],md5($pass),$_POST['email']){
 mail($_POST['email'],'pass','pass = '.$pass);
 echo 'Registration success, your password was send to your email' ;
} else 'Your login or email is already in use' ;

Функцию saveuser нужно реализовать так, чтобы она возвращала true в случае если регистрация прошла успешно, и false если логин или емаил уже использован. Ну дальше вроде тоже всё просто. Единственный минус хранения не самого пароля, а его хеша в том, что при remind password придется не напоминать пароль, а генерить заново. Теперь я хочу поговорить о самом интересном – об авторизации. 
Если на каждой странице сайта юзеру придёться заново вводить пароль – это будет мягко сказать неудобно. По этому, в голову приходят 2 мысли – ассоциировать компьютер с юзером, или хранить пароль на машине юзера, и заставлять машину юзера отсылать пароль автоматический при заходе на сайт. Оба способа имеют свои плюсы и минусы. Рассмотрим первый способ.
Ассоциировать можно либо по IP адресу, либо по mac (хотя как это сделать по mac я чесно говоря не очень в курсе.. и зачем это надо тоже не понимаю). Но! Если 2 юзера зайдут через один прокси сервер? Ничего хорошего при этом не произойдёт. Так же весесло будет сотрудникам одной фирмы, которые заходят в инетрнет через NAT. Так что этот вариант отпадает (хотя я видел такие реализации).
Многие сайты хранят пароль юзера в его кукисах (если вы внимательно читали прошлую статью, вы должны были уже узнать что это такое), однако, во первых, если кто - то получит доступ к машине юзера, этот кто – то сразу смотрит узнать его пароль. Так что это не секьюрно.
Один известный форум (не будем переходить на личности) делает совсем смешную вещ – на сервере пароль храниться в виде текста, а в куксиах он хранит пароль в виде md5 хеша. Конечно, в этом есть свою плюсы, однако, в таком случае, если достать этот md5 хеш, и вставить его в свои кукисы, ты получишь доступ к акаунту, и тебе просто не нужен будет настоящий пароль.
У пытливых умов возникает вопрос: а как же получить кукисы? На это я отвечаю – очень просто. Большинство сайтов имеет уязвимости, которые позволяют вставить ява - скрипты. Конечно, программисты по всякому стараються предотвратить это, однако, почти все самодельные сайты что я видел, первые месяцы жизни просто кишат этими дырами. Когда кто ни - нибудь их начинает юзать, тогда админы их замечают и заделывают, но всё таки с ними бороться сложнее чем с SQL уязвимостями. Пока я не буду вдоваться в подробности, эта тема на столько огромная, что ей нужно посвятить отдельную, возможно даже не одну статью. Но пока поверьте, что потенциальная возможность получить кукисы есть. И для этого не нужно иметь крэкер Интернета.
Выход из этого есть – сессии. Сессии это воистину мощная вещ. На сервере храниться лишь идентификатор сессии, ты просто вставляеш в начало сценария session_start() а дальше РНР всё делает за тебя. Ты можешь определять любые переменные сессии, а юзер об этом даже не узнает. Обычно, идентификатор сессии храниться в кукисах, в зависимости от настроек РНР или от возможностей юзера (например, некоторые юзеры запрещают кукисы) он может так же храниться в адресной строке, и передоваться методом GET. На сервере создаётся файл, с названием как у идентификатора сессии, и в этом фаиле хранятся все переменные сессии. Именно с этой частью чаще всего бывают траблы, на некоторых серверах админ может запретить запись из скриптов в папку /tmp. Хотя серверов много, и в каждом всё по разному…
Конечно, можно так же украсть и идентификатор сессии, и зайти под чужим акаунтом, но это во многом усложняет задачу. Дело в том, на некоторых серверах идентификаторы сезонов имеют определённый срок жизни, и скажем, через пол часа идентификатор становиться мёртвым.
Из этой статьи может сложиться впечатление, что авторизация не может быть в безопасности, и это правда. Хотя самые крутые сайты пишут что – то вроде своего session_start();. Недавно, мне попался на глаза сайт, которые ассоциировал идетификатор сезона с IP адресом, и это резко повышало безопасность, однако повышало возможность ошибок. Есть и другие хитрые способы, однако такие функции обычно резко повышают стоимость и срок разработки проекта, так что редко когда это является действительно востребовано. Хочу ещё поделиться своим мнением на счёт одного сайта. Я видел сайт (вы его вряд ли знаете, однако это что – то похожие на смесь почты и чата), где срок жизни идентификатора сезона очень маленький. Я к сожалению сорца не видел (хотя там наверное самодельные сезоны), но по моим примерным расчётам сезон умирает через 5-10 минут. Это конечно секьюрно, но там не автоматического рефреша. То есть когда оставляешь открытым окошко, ждёш например письма, 15 минут не делал рефреш и снова приходиться набирать пароль и логинеться… но совсем раздражает когда пишешь большое деловое письмо минут 20, посылаешь, а он вместо того чтобы послать предлагает ещё раз ввести пароль и заново набрать письмо.
Последнее о чём я хочу рассказать – функция «Кто он лайн». К сожалению, по этому поводу нет встроенных функций в PHP. По крайне мере я ничего об этом не слышал. Самое простое – когда человек обновляет страницу, он заноситься в список юзеров кто он лайн, и время когда он это делает так же заноситься в этот список. Если он не обновляет страницу 15 минут, то его оттуда вычёркивают. Для точности так же можно в страницу встроить скрытый фрейм, которые обновляется каждые 5 минут. А чтобы было удобно и тем у кого модем на 10 байт в секунду, этот фрейм кроме как кукисы ничего не должен посылать и принимать.
К сожалению, я не привёл примеров авторизации, однако мне кажется что я достаточно описал различные проблемы, и те кто хочет сам сможет теперь написать хороший сайт с регистрацией. Следующие статьи я планирую посвятить базе данных MySQL, и тогда мы сможем создавать маленькие, но очень мощные сценарии.

Добавить комментарий


Обновить