Jump to content
  • 0

Недостатки моего кода


li4e
 Share

Question

Добрый день, собственно вопрос в том почему код ниже является плохим?

Появилась необходимость запретить просмотр определенной страницы посторонним и решил изучить php и реализовать хоть какую никакую авторизацию и разграничение доступа! Так то я сделал и все работает, но есть сомнения на счет безопасности!

 

Сомнения появились, после того как я просмотрел примеры авторизации на различных сайтах, они там вместе с сеансами используют еще и куки, и пароль шифруют. Но как я понял все переменные $_SESSION хранятся на сервере, тогда чего мне бояться? Заранее спасибо!

 

Файл "check.php" его я размещаю в начало страниц, к которым нужно закрыть доступ

<?phpsession_start();if (isset($_GET['logout'])) { //Это для выхода из аккаунта, просто GET запросомunset($_SESSION['auth']);}if (isset($_SESSION['auth']) AND ($_SESSION['level'] == 1)) //Проверка, авторизован ли пользователь и какими правами доступа обладает{}elseif (isset($_SESSION['auth'])) {header('Location: /index.php');//Если авторизован, но без прав доступа, то редиркет на гланую сайтаexit();}else{header('Location: /admin/auth.php'); //Если не авторизован, то предлагаю авторизоваться}?>

А вот и сам код авторизации "auth.php"

<?phpinclude '../config.php'; //Подключаю конфиги для соединени с бдsession_start();if ($_POST['submit']) //Действия по нажатию кнопки войти{if (empty($_POST['login']) OR empty($_POST['password'])) //Проверка на заполненность полей, чтобы не были пустыми{$error = "<p id='error'>Заполни поля!</p>";}else{//дальше идет поиск введенных значений в бд$data = mysql_fetch_array(mysql_query("SELECT login, password, level FROM users WHERE login='".$_POST[login]."' AND password='".$_POST[password]."'"));if (($_POST['login'] == $data[login]) AND ($_POST['password'] == $data[password])) {$_SESSION['auth'] = '1';$_SESSION['level'] = $data[level];header('Location: /admin/index.php');}else{$error = "<p id='error'>Неверный логин или пароль!</p>";}}}if (isset($_SESSION['auth'])) //Если пользователь уже авторизован, его кидает на главную страницу админки{header('Location: /admin/index.php');}else{include "tmp/header.php";echo '<div id="nav-wrapper">	<ul id="sidebar">		<li><a href="../index.php">Главная</a></li>	</ul></div><form method="POST" id="auth">'.$error.'<h1>Вход в ПУ</h1>  Логин <br><input class="s" name="login" type="text"><br>   Пароль <br><input class="s" name="password" type="password"><br>   <input style="width: 100px;" name="submit" type="submit" value="Войти">   </form>';include "tmp/footer.php";}?>
Edited by li4e
Link to comment
Share on other sites

20 answers to this question

Recommended Posts

  • 0

Спасибо, сейчас почитаю!


Значит после успешной авторизации, мы должны назначить уникальный идентификатор пользователю и записать его в бд в строку пользователя, заранее создав спец поле для этого?

Ну и затем занести в куки?

Link to comment
Share on other sites

  • 0

НИКОГДА так не делай:

mysql_query("SELECT login, password, level FROM users WHERE login='".$_POST[login]."' AND password='".$_POST[password]."'")

Давать возможность пользователю воткнуть данные в SQL-запрос "как есть", без "фильтрации" - первая "дыра" в безопасности, которую будут искать.

Вот во что пойдет на выполнение, если закинуть в $_POST[login] строку "1' OR true limit 1; -- \"(это называется SQL-инекция):

SELECT login, password, level FROM users WHERE login='1' OR true LIMIT 1; -- \' AND password=''

Как минимум строки нужно пропускать через addslashes(), числа перегонять в числа через (int/float):

mysql_query("SELECT login, password, level FROM users WHERE login='".addslashes($_POST[login])."' AND password='".addslashes($_POST[password])."'")

Еще обязательно проверяй количество найденных записей по паре значений логин и пароль. Мало того, что они должны существовать, - они еще должны быть в единственном числе.

  • Like 1
Link to comment
Share on other sites

  • 0

НИКОГДА так не делай:

mysql_query("SELECT login, password, level FROM users WHERE login='".$_POST[login]."' AND password='".$_POST[password]."'")

Давать возможность пользователю воткнуть данные в SQL-запрос "как есть", без "фильтрации" - первая "дыра" в безопасности, которую будут искать.

Вот во что пойдет на выполнение, если закинуть в $_POST[login] строку "1' OR true limit 1; -- \"(это называется SQL-инекция):

SELECT login, password, level FROM users WHERE login='1' OR true LIMIT 1; -- \' AND password=''

Как минимум строки нужно пропускать через addslashes(), числа перегонять в числа через (int/float):

mysql_query("SELECT login, password, level FROM users WHERE login='".addslashes($_POST[login])."' AND password='".addslashes($_POST[password])."'")

Еще обязательно проверяй количество найденных записей по паре значений логин и пароль. Мало того, что они должны существовать, - они еще должны быть в единственном числе.

И то же самое, если будете использовать Cookie. Их тоже можно легко подменить на SQL инъекцию. А вообще лучше не addslashes, а htmlspecialchars.

  • Like 1
Link to comment
Share on other sites

  • 0

Ну htmlspecialchars обычно полюзуют при вставке в базу именно html-кода, который в последствии будет воспроизводиться на странице, дабы не воткнули туда всякой гадости типа скриптов. А для данных типа логина, думаю, достаточно и экрана: строки не "раздуваются". Дастаточно htmlspecialchars пользовать при выводе логина, как данных на сайте.

Хотя это уже дело логики.

  • Like 1
Link to comment
Share on other sites

  • 0

достаточно будет написать вот такую простенькую ф-цию:

	// Функция экранирования переменных	function quote_smart($value) {    // если magic_quotes_gpc включена - используем stripslashes    	if (get_magic_quotes_gpc()) {			$value = stripslashes($value);    	}    // Если переменная - число, то экранировать её не нужно    // если нет - то окружем её кавычками, и экранируем    	if (!is_numeric($value)) {			$value = mysql_real_escape_string($value);    	}   		return $value;	}

использовать так:

$login =$this->quote_smart($_POST['login']);

и можно особо не париться на счет инъекций.

Link to comment
Share on other sites

  • 0

Все таки Я еще раз прочитал статью, ссылку на которую вы скинули выше! И почитал про различные методы авторизации, конечно с тем что надо обрабатывать вводимую пользователем информацию все ясно, но вот все никак не могу понять логику, почему нельзя использовать для авторизации только сессии? Ведь они же все равно хранятся на сервере и не доброжелатель не сможет никак подменить данные, как в случае с куками! Объясните пожалуйста!

Link to comment
Share on other sites

  • 0

rus, не советуй людям глупости всякие. Модуль mysql уже устарел. А использовать надо prepared statements и всем будет счастье.

почему сразу глупость? ведь на жигули "шестерках" до сих пор катаются, разве нет?

pdo конечно крут, но списывать со счетов mysql пока что рано мне кажется.

к стати, перевод по твоей ссылке: http://php.net/manual/ru/pdo.prepared-statements.php все-же читается лучше )

Link to comment
Share on other sites

  • 0

Все таки Я еще раз прочитал статью, ссылку на которую вы скинули выше! И почитал про различные методы авторизации, конечно с тем что надо обрабатывать вводимую пользователем информацию все ясно, но вот все никак не могу понять логику, почему нельзя использовать для авторизации только сессии? Ведь они же все равно хранятся на сервере и не доброжелатель не сможет никак подменить данные, как в случае с куками! Объясните пожалуйста!

да можно в принципе и без кук, просто куки - это для удобства идентификации вас (вашего браузера) при повторном входе, а в плане защиты все-таки нужно использовать шифрование пароля.

  • Like 1
Link to comment
Share on other sites

  • 0

Т.е просто шифровать пароль, и использовать такую авторизацию как у меня выше будет нормально в плане безопасности? Ну естественно обрабатывая вводимую информацию предворительно.

Link to comment
Share on other sites

  • 0

да, можно.

как пример:

/*** Функция для генерации соли, используемоей в хешировании пароля** возращает 3 случайных символа*/function GenerateSalt($n=3){	$key = '';	$pattern = '1234567890abcdefghijklmnopqrstuvwxyz.,*_-=+';	$counter = strlen($pattern)-1;	for($i=0; $i<$n; $i++)	{		$key .= $pattern{rand(0,$counter)};	}	return $key;}

использовать:

$salt = GenerateSalt();$hashed_password = md5(md5($password) . $salt);

теперь в $hashed_password находится зашифрованный пароль.

Link to comment
Share on other sites

  • 0

if (isset($_SESSION['auth']) AND ($_SESSION['level'] == 1)) //Проверка, авторизован ли пользователь и какими правами доступа обладает {}elseif (isset($_SESSION['auth']))  {}else {}
Тут можно чуть облегчить понимание кода, убрав повторяющееся условие

if (isset($_SESSION['auth'])){if ($_SESSION['level'] == 1) {}else {}}else {}
А ещё не нужно писать $_POST[password], потому что контанта password наверняка не определена. Такое прокатывает в Perl.

$_POST['login'] == $data[login]

Вот же, про кавычки знаешь, но почему-то тут же забываешь. Или где-то всё же есть константы, просто не показаны?

С заменой || и && на or и and нужно быть поаккуратнее, если делаешь это не сознательно, потому что приоритет у "буквенных" оператров ниже, чем у присваивания и тернарного оператора, тогда как у || и && — выше.

  • Like 1
Link to comment
Share on other sites

  • 0
if (isset($_SESSION['auth']) AND ($_SESSION['level'] == 1)) //Проверка, авторизован ли пользователь и какими правами доступа обладает {}elseif (isset($_SESSION['auth']))  {}else {}
Тут можно чуть облегчить понимание кода, убрав повторяющееся условие
if (isset($_SESSION['auth'])){if ($_SESSION['level'] == 1) {}else {}}else {}
А ещё не нужно писать $_POST[password], потому что контанта password наверняка не определена. Такое прокатывает в Perl.

$_POST['login'] == $data[login]

Вот же, про кавычки знаешь, но почему-то тут же забываешь. Или где-то всё же есть константы, просто не показаны?С заменой || и && на or и and нужно быть поаккуратнее, если делаешь это не сознательно, потому что приоритет у "буквенных" оператров ниже, чем у присваивания и тернарного оператора, тогда как у || и && — выше.

Нет, константы не описаны, просто не набил ещё руку. Насчёт остального спасибо, учту!

Link to comment
Share on other sites

  • 0
$_SESSION['auth'] = '1';

Тут лучше делать так:

$_SESSION['auth'] = true;

Тогда можно будет делать просто так:

if ($_SESSION['auth'])...

Да и 1 бит (вроде столько занимает в ОЗУ boolean) меньше символьного значения 1 (вроде 1 байт), что позволяет экономить процессорное время и ресурсы сервера.

Edited by iKNG
Link to comment
Share on other sites

  • 0
Да и 1 бит (вроде столько занимает в ОЗУ boolean) меньше символьного значения 1 (вроде 1 байт), что позволяет экономить процессорное время и ресурсы сервера.

 

Минимальная адресуемая единица памяти 1 Байт.

Link to comment
Share on other sites

  • 0

 

Да и 1 бит (вроде столько занимает в ОЗУ boolean) меньше символьного значения 1 (вроде 1 байт), что позволяет экономить процессорное время и ресурсы сервера.

 

Минимальная адресуемая единица памяти 1 Байт.

 

Все равно, с булевым типом в данном случае удобнее, чем со строками.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Similar Content

    • By Only091
      Помогите пожалуйста, не получается сделать постраничную навигацию. Делал все по урокам. в Итоге получилось сделать два разных каталога один с фильтрами другой с постраничной навигацией. И теперь я пытаюсь объединить два каталога. Но не получается. Сами файлы урока в архике каталог. Буду очень благодарен если мне помогут! catalog.phpcatalogDB.js
      каталог.7z
    • By stonelabs
      Всем привет!

      Наша компания (https://stone-labs.com/) ищет команды (!) разработчиков для реализации ряда заказных проектов. Местоположение не важно - мы практикуем удаленную работу.
       
      Обязательные требования:
      Laravel или Symfony frameworks jQuery (UI), JavaScript, Ajax, Bootstrap MySQL REST API, опыт внедрения Third-party APIs английский на уровне чтения и понимания технической документации опыт в разработке веб приложений и их архитектуры с нуля корректное использование git & pull request flow работа в дневное время во временной зоне UTC +3  
      Будет плюсом, если у вашей команды есть:
      опыт с GitLab CI/CD, Jenkins опыт с MySQL Cluster, MongoDB, PostgreSQL, Redis опыт с Vue.js опыт Linux администрирования, SSH, Nginx, DevOps  
      Если вам интересно сотрудничество, пожалуйста, пишите на наш ящик wanted@stone-labs.com 
    • By Defroing
      <form method="POST" action= "action_handler.php" id="form"> <section class="table_1"> <table class="iksweb"> <tbody> <tr> <td rowspan="3"><b>История компании «Mc donald's»</b> <h3 class="the">Кто основал компанию «Mc donald's»?</h3> <section class="conteiner"> <div class="checkbox"> <input type="checkbox" class="i-6" id="i6" value="0" name="formDoor[]"> <label for="i6" tabindex="12">Роналд Макдоналд</label> </div> <div class="checkbox"> <input type="checkbox" class="i-6" id="i7" value="0" name="formDoor[]"> <label for="i7" tabindex="13">Рэй Крок</label> </div> <div class="checkbox"> <input type="checkbox" class="i-6" id="checkbox_68" value="1" name="formDoor[]"> <label for="checkbox_68" tabindex="14">Братья Дик и Мак Макдоналд</label> </div> <div class="checkbox"> <input type="checkbox" class="i-6" id="checkbox_170" value="0" name="formDoor[]"> <label for="checkbox_170" tabindex="14">Клинт Иствуд</label> </div> <div class="out-block out-6"></div> </section> </td> </tr> </tbody> </table> <div class="dsw"> <button class="b-6" tabindex="11" id="btn-1" type="submit" name="formSubmit">Отправить</button> </div> </form> <?php mysql_connect("localhost", "root", ""); mysql_select_db('olala') or die(mysql_error()); if(isset($_GET['submit'])){ $arr=$_GET; foreach ($arr as $key => $value) { $reg="/^check/";//отбираю нужные элементы if( preg_match ($reg,$key )) { //$new_mass[]=$arr[$key]; //print_r($new_mass); echo $arr[$key]; $sql_1="INSERT INTO `table_one` (`name`) VALUES('$arr[$key]')"; mysql_query($sql_1) or die(mysql_error()); } } } ?>  Создаю опросник и хочу, чтобы чекбоксы заносились в БД(таблицу пока не создавал). Хотелось узнать на счёт php кода, сможете подсказать, что в нём не так (дать какие нибудь советы). В openserver опросник пока не выкладывал.
    • By seoww
      Доброго времени суток. Я не сильно знающий веб-разработчик, но учусь. Начал создавать интернет магазин. Написал код самого сайта, посмотрел видео как делаются интернет-магазины и теперь не могу разобраться с PhpMyAdmin. Я не понимаю как она взаимодействует с сайтом. В интернете погуглил, так ничего дельного найти и не смог. Помогите пожалуйста.
      P.S сильно в меня камни не кидайте, я только учусь 
      Всем добра!
    • By Gmansurov
      Нужно отправить текст на сайт, не знаю как это сделать и не могу найти форумы по этим темам. Google Cloud Platform. Помогите пожалуйста.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy