Я знаю, что это было спрошено миллиарды раз, но я супер параноид / OCD о безопасности моего кодирования. Я работаю над небольшим проектом. Данные сеанса будут содержать только:
user_id 1
имя_пользователя MyUsername
logged_in true
csrf_token 87cc51ee94178df79cccce2aebc45d53
Вот мой код. Является ли он достаточно безопасным для использования на небольшой CMS?
session_start(); ini_set('session.cookie_httponly', 'On'); ini_set('session.cookie_secure', 'On'); ini_set('session.use_cookies', 'On'); ini_set('session.use_only_cookies', 'On'); $rand = rand(1, 10); if ($rand != 1 || $rand != 3 || $rand != 5) session_regenerate_id(); $user_ip = md5($_SERVER['REMOTE_ADDR']); $user_agent = md5($_SERVER['HTTP_USER_AGENT']); if (isset($_SESSION['user_ip'], $_SESSION['user_agent'])) { $session_user_ip = $_SESSION['user_ip']; $session_user_agent = $_SESSION['user_agent']; if ($session_user_ip != $user_ip || $session_user_agent != $user_agent) { unset($_SESSION); session_destroy(); die('Error'); } } else { $_SESSION['user_ip'] = $user_ip; $_SESSION['user_agent'] = $user_agent; }
Затем вызывать сеансы:
$_SESSION['user_id'] = 1; $_SESSION['user_name'] = 'MyUsername'; // etc.
Дополнительная информация
Я буду использовать данные сеанса, чтобы проверить, разрешено ли пользователю делать что-либо. Пример: if ( user_has_perm( $_SESSION['user_id'] ) )
Заранее благодарны за Вашу помощь.
Риски безопасности сеанса исходят из трех различных возможностей:
Предсказание означает, что кто-то, кто не является пользователем, для которого был создан сеанс, угадал их идентификатор сеанса. Шансы на это почти равны 0, хотя они растут, так как все больше пользователей используют сайт одновременно.
С вашим кодом вы рискуете еще меньше, потому что он будет работать только в том случае, если злоумышленник поделился пользовательским агентом и ip прогнозируемого сеанса. Но в этом случае разница тривиальна.
Фиксация означает, что злоумышленник может создать сеанс, а затем заставить другого пользователя использовать свой сеанс. В этом случае это будет зависеть: если злоумышленник знает, что вы это делаете, и они подделывают агент пользователя и ip клиента, они могут фиксировать сеанс. Или, если они совместно используют ip и агент пользователя.
И, наконец, у нас есть захват сеанса, вероятно, самый распространенный метод этих трех. В этом случае злоумышленник каким-то образом получит доступ к идентификатору сеанса действительного зарегистрированного пользователя, а затем будет использовать его для входа в свою учетную запись. Как и в предыдущем методе, это будет работать только для них, если они знают, что вы проверяете ip и пользовательский агент и подделываете те же, что и пользователь. Техника, которую вы используете, не уникальна, и некоторые нападавшие могут нападать на них на всякий случай.
Это, как говорится, безопасно? Да и нет
Если вы одержимы безопасностью, ответ всегда один и тот же: используйте SSL
Если ваш код не является открытым исходным кодом, почти все, что вы делаете, что изменяет поведение сессий php, будет достаточно безопасным.
Единственное исключение – это действительно популярные сайты, которые привлекут внимание хакеров.
Существует очень хорошая документация по этой теме:
Я не эксперт по безопасности. Однако я смиренно сомневаюсь в том, что ваши меры безопасности приведут к существенным преимуществам.
Если есть кто-то, кто может украсть идентификатор сеанса ваших пользователей, например, подслушивая незашифрованную беспроводную сеть, я готов поспорить, что он может украсть также имя пользователя и пароль, которые ваши пользователи отправляют на ваш сервер при их аутентификации. После того, как у него есть учетные данные доступа, злоумышленник может войти в систему через день или неделю, а также будет иметь свою «безопасную» и 100% действительную сессию.
Я считаю, что нет безопасности сеанса без защиты канала. Если вы используете SSL , вы гарантируете, что идентификатор сеанса отправляется только через файлы cookie (вы уже это делаете), и ваши сеансы истекают в ближайшее время, я считаю, что вы достаточно безопасны и безопаснее, чем выполнение этих принудительных действий на небезопасном канале.
Во-первых, у вас есть ошибка в регенерирующем коде сеанса. Следующее, если всегда будет оцениваться как true:
if ($rand != 1 || $rand != 3 || $rand != 5)
Если $rand
не 1, он возвращает true. Если $rand
равно 1, то это не три, и он возвращает true. Вы, вероятно, хотели использовать and
здесь.
Во-вторых, вам не нужно использовать MD5 user_ip
или строки user_agent
. Если кто-то может напрямую получить доступ к данным сеанса на вашем сервере, вы настолько глубоко в нем, что хеширование этих данных не спасет вас.
ПОДТВЕРЖДЕНИЕ: Поскольку SDC и подавление указывают в комментариях, MD5 хорош для хэширования паролей, если вы используете его с солью . Это означает, что пароли вашего пользователя в целом по-прежнему безопасны, даже если атака SQL Injection завершается успешно, и ваша база данных находится в мире. Однако, если ваш сервер взломан, а соль скомпрометирована, становится возможным создать набор известных хэшей и попытаться выполнить обратный поиск определенного пароля. Нижняя линия? Хеши ваши пароли пользователей с солью.
В-третьих, большинство дыр в безопасности не происходят из сеансов спуфинга. Они происходят из-за плохой проверки ввода. Книга, подобная Essential PHP Security, должна быть хорошим знакомством с типом проверки ввода, которую вы должны делать в проекте PHP. В противном случае, по крайней мере, прочитайте раздел безопасности Руководства по PHP . Обратите внимание на бит SQL Injection. Это круто!
Наконец, я полностью согласен с другим плакатом, что вы должны использовать SSL для обеспечения связи с вашим сайтом.
Честно говоря, я думаю, что вы слишком осторожны, но не очень полезны.
Если вы действительно беспокоитесь о безопасности сеансов, не пытайтесь сделать это сами. Используйте патч для защиты PHP, такой как Suhosin . Пусть он сделает для вас всю тяжелую работу. Suhosin – это хорошо зарекомендовавший себя патч для PHP. Он включает в себя материал, который касается всех способов взлома PHP-сессии. Если вы его установили, вам не нужно делать что-либо дополнительно, чтобы обеспечить безопасность сеанса. Если вы его не установили, то вы определенно не можете претендовать на супер-параноик о безопасности!
Короче говоря, установите Suhosin (если вы еще этого не сделали) и забудьте об этом.
Но только для полноты, я сделаю несколько комментариев в вашем фактическом коде, просто чтобы указать на несколько вещей:
Я не уверен, почему вы думаете, что хеширование MD5 имеет значение. Хеши MD5 могут быть взломаны за считанные секунды, поэтому их использование в любой функции безопасности абсолютно произвольно. Это может быть простой текст. Тем не менее, я действительно не вижу необходимости в том, чтобы они были чем-то другим, кроме обычного текста – если хакеру удалось получить данные сеанса, чтобы читать IP-адрес, который он содержит, то вы уже не беспокоясь о том, знают ли они IP-адрес или нет.
Выберите изображение для загрузки: «; $ res = mysql_query (« SELECT `id`,` FirstName`, `LastName`,` Address`, `Password`,` Repassword`, `Birthday`,` Gender`, `user_image` FROM `account`) или die (mysql_error ()); while ($ row = mysql_fetch_array ($ res)) {$ id = $ row ['id']; $ firstname = $ row ['FirstName']; $ user_image = $ row ['user_image']; $ page. = "$ firstname";} $ page. = ""; $ res_post = mysql_query ("SELECT post_info.post_info_id, post_info.id, post_info.post_info_desc, registration.FirstName FROM` post_info `join` registration` WHERE post_info.id = register.id order by post_info.post_info_id desc ") или умереть (mysql_error ()); while ($ row_post = mysql_fetch_array ($ res_post)) {$ post_id = $ row_post ['post_info_id' ]; $ post_desc = $ row_post ['post_info_desc']; $ id = $ row_post ['id']; $ FirstName = $ row_post ['FirstName']; $ page. = "
$ post_desc
<?php session_start(); $con=mysql_connect("localhost","root",""); $seldb=mysql_select_db('myfreind', $con); $email=$_POST['txtEmail']; $password=$_POST['txtPass']; $res=mysql_query("SELECT `id`, `FirstName`, `LastName`, `Address`, `Password`, `Repassword`, `Birthday`, `Gender` FROM `registration` WHERE `Password`='$password' and `FirstName`='$email'"); $num=mysql_num_rows($res); if($num==1) { $row=mysql_fetch_array($res); $id=$row['id']; $firstname=$row['FirstName']; $_SESSION['id']=$id; $_SESSION['FirstName']=$firstname; //echo $_SESSION['id']; header('Location:main.php'); }else { header('Location:index.php?error'); } ?>