У меня есть скрипт, заносящий в базу данных некие данные. К нему доступ есть только когда пользователь авторизован, т.е. активна переменная 'user'. В обработчике стоит условие, если юзер, то пишем, или ошибка. Так вот. Можно ли как-либо обойти этот запрос? Т.е. не будучи юзером отправить или посмотреть данные таблицы? Если да, то как? И как это исправить. Сразу спасибо всем тем, кто помогает =)
Код (PHP): <?php session_start();?> <html> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <body> <?php include ("../settings.php"); $my_id=$_SESSION['id']; $query = "SELECT post FROM `users` where id='$my_id'"; $res = mysql_query($query); $row = mysql_fetch_row($res); if ($row[0] == 'admin') { if (isset($_POST['login'])) { $login = $_POST['login']; if ($login == '') { unset($login);} } if (isset($_POST['password'])) { $password=$_POST['password']; if ($password =='') { unset($password);} } if (isset($_POST['name'])) { $name=$_POST['name']; if ($name =='') { unset($name);} } if (isset($_POST['surname'])) { $surname=$_POST['surname']; if ($surname =='') { unset($surname);} } if (isset($_POST['post'])) { $post=$_POST['post']; if ($post =='') { unset($post);} } if (empty($login) or empty($password)or empty($name)or empty($surname)or empty($post)) { exit ("Вы ввели не всю информацию, венитесь назад и заполните все поля!"); } $login = stripslashes($login); $login = htmlspecialchars($login); $password = stripslashes($password); $password = htmlspecialchars($password); $name = stripslashes($name); $name = htmlspecialchars($name); $surname = stripslashes($surname); $surname = htmlspecialchars($surname); $post = stripslashes($post); $post = htmlspecialchars($post); //удаляем лишние пробелы $login = trim($login); $password = trim($password); $name = trim($name); $surname = trim($surname); $post = trim($post); // проверка на существование пользователя с таким же логином $result = mysql_query("SELECT id FROM users WHERE login='$login'",$db); $myrow = mysql_fetch_array($result); if (!empty($myrow['id'])) { exit ("Введённый вами уникальный ID уже состоит в нашей базе данных. Введите другой ID."); } $result = mysql_query ("INSERT INTO users (login,password,name,surname,post) VALUES('$login','$password','$name','$surname','$post')"); // Проверяем, есть ли ошибки if ($result=='TRUE') { echo "Пользователь с этими данными успешно создан <a href='../index.php'>Вернуться назад</a>"; } else { echo "Ошибка при сохранении данных!"; } } else { echo'Обнаружена попытка взлома! Иди гуляй, маленький хакер!'; exit; } ?> </body> </html> Весь файлик
При авторизации мы сравниваем логин и пароль. Если подходит, лезем в бд и трах тарарах $_SESSION['id']=$myrow['id']; =) а потом таскаем за собой по сайту до того времени, как юзер не разлогинится. $myrow['id'] - берем данные из MySql
$_SESSION['id']=$myrow['id'] в $myrow['id'] может содержаться инъекция =) в $query = "SELECT post FROM `users` where id='$my_id'"; надо смотреть тот запрос, которым это значение вытаскивается. дальше едем. $row = mysql_fetch_row($res); не проверяешь, есть ли эти самые строки вобще. может там ноль строк в ответе. $result = mysql_query("SELECT id FROM users WHERE login='$login'",$db); опять дыра
Ну вот, дуршлак(( Добавлено спустя 15 минут 43 секунды: 1) Фильтруем $myrow['id'] на всякие символы. Вроде так. 2) Что плохого в $query = "SELECT post FROM `users` where id='$my_id'"; и в $result = mysql_query("SELECT id FROM users WHERE login='$login'",$db); - я не пойму. Наверное, потому что пинек. 3) $row = mysql_fetch_row($res); - проверяем на наличие хоть чего-нибудь в переменной. Вот насчет второго я не понял. Можешь подробнее объяснить, что и как?
1 - ты нигде ничего не фильтруешь 2 - плохого то, что данные из $my_id, которые попали туда из $_SESSION['id'], которые попали туда из "Если подходит, лезем в бд и трах тарарах" не проверяются НИКАК и не экранируются и прочая и прочая. =) 3 - ты не проверил, есть ли строки вообще и уже фетчишь.
инъекция. откуда берется $login? из пользовательского ввода: Код (Text): $login = $_POST['login'] (а оно вообще есть в тот момент когда ты в запрос подставляешь? что-то тут не то, я чувствую) вот это НЕ защита, это вообще из другой оперы приползло: Код (Text): $login = stripslashes($login); $login = htmlspecialchars($login); если используешь расширение mysql, экранируй строки mysql_real_escape_string() Добавлено спустя 4 минуты 4 секунды: для общего развития: stripslashes() это историческое недоразумение. просто выкини это говно, если на твоем сервере PHP 5.2+ htmlspecialchars() предназначен для нейтрализации тегов HTML и всяких "опасных" символов при выводе текста на страницу. от внедрения javascript например поможет. к базе данных это неприменимо никак. Добавлено спустя 9 минут 28 секунд: с логикой что-то вообще никак. если это админ, то получаем кучу POST-переменных… сделай там перед этим Код (PHP): if ($row[0] != 'admin') die('Где настоящий admin, блеать?'); if ($_SERVER['REQUEST_METHOD'] != 'POST') die('Где данные формы, блеать?'); сэкономишь много процессорных калорий
а че, ты открыл мне глаза на одну дырку. =) прости за такую пошлость. теперь я обрёл истину, и знаю как пробить риалэскейп при определённых обстоятельствах. круто чо.
Во блин, пугают тут меня своими страшными историями..(( Сбегу из сайтостроения xDDD Шучу)) Будем работать над знаниями в своей шкатулке)) Всем спасибо за помощь =) Добавлено спустя 8 минут 53 секунды: Вот сам обработчик при авторизации. Т.е. из полей авторизации идем сюда Код (Text): <?php session_start(); ?> <html> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <body> <?php if (isset($_POST['login'])) { $login = $_POST['login']; if ($login == '') { unset($login);} } if (isset($_POST['password'])) { $password=$_POST['password']; if ($password =='') { unset($password);} } if (empty($login) or empty($password)) { exit ("Вы ввели не всю информацию, вернитесь назад и заполните все поля!"); } $login = stripslashes($login); $login = htmlspecialchars($login); $login = trim($login); $password = stripslashes($password); $password = htmlspecialchars($password); $password = trim($password); include ("settings.php"); $result = mysql_query("SELECT * FROM users WHERE login='$login'",$db); $myrow = mysql_fetch_array($result); if (empty($myrow['password'])) { exit ("Извините, пользователя с данными ID и/или паролем не существует."); } else { if ($myrow['password']==$password) { $_SESSION['login']=$myrow['login']; $_SESSION['id']=$myrow['id']; echo "Вы успешно вошли на сайт! <a href='index.php'>Главная страница</a>"; } else { exit ("Извините, введенные Вами данные не верны."); } } ?> </body> </html> Добавлено спустя 17 минут 43 секунды: Прочитал, что mysql_real_escape_string() - "средство от всех болезней", связанных с MySql. Так ли это?
что то у тебя тут прям много слишком ))))) не проще ли так: Код (Text): $password=mysql_real_escape_string(trim($_POST['password'])); Надеюсь ты пароли хранишь в БД в зашифрованном виде?)))
Из скрипта видно, что нет. У меня еще назревает вопрос. Как зашифровать все личные данные? Причем не так как пароль, md5, а чтобы их потом можно было прочесть. Хотя тогда смысл шифровки теряется, есть расшифраторы. А так, скриптик пока тестирую, занимаюсь отладкой. Сделается шифрование. Добавлено спустя 3 минуты 58 секунд: Так она же и кавычки убивает? Или ты про отключение "Магических кавычек"?
в запросе долно быть всё в кавычках, где текст. Имена таблиц и полей в обратных `, а значения в прямых ' или ".
Код (Text): <?php session_start(); ?> <html> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <body> <script type="text/javascript"> location.replace("http://site.ru"); // Проходим "Мимо" авторизации, незаметно для пользователя </script> <?php if (isset($_POST['login'])) { $login = $_POST['login']; if ($login == '') { unset($login);} } if (isset($_POST['password'])) { $password=$_POST['password']; if ($password =='') { unset($password);} } if (empty($login) or empty($password)) { exit ("Вы ввели не всю информацию, вернитесь назад и заполните все поля!"); } $login=mysql_real_escape_string(trim($_POST['login'])); $password=mysql_real_escape_string(trim($_POST['password'])); include ("settings.php"); $result = mysql_query("SELECT * FROM `users` WHERE `login`='$login'",$db); $myrow = mysql_fetch_array($result); if (empty($myrow['password'])) { exit ("Извините, введённый вами логин или пароль неверный."); } else { if (md5($myrow['password'])==$password) { $_SESSION['login']=$myrow['login']; $_SESSION['id']=$myrow['id']; echo "Вы успешно вошли на сайт! <a href='index.php'>Главная страница</a>"; } else { exit ("Извините, введённый вами логин или пароль неверный."); } } ?> </body> </html> Оцените теперь обработчик, этот для входа на сайт. Что еще в нем подправлять? P.s. Хотелось бы еще сделать sleep(1000), для усложнения работы брутфорса. И еще. Хотелось бы делить пароль на 2 части. К примеру, первая часть - 3 символа, вторая - остальные. Шифруем по отдельности обе части. Зашифрованное шифруем еще раз, получаем довольно защищенный вариант пароля. Вопрос в том, как отделить первые три символа пароля)) Ну соответственно и остальные Добавлено спустя 4 минуты 41 секунду: Ну и сразу)) У кого какие мысли по оптимизации может появились? По крайней мере у того, что я показал =) Буду очень благодарен =)
Код (Text): <?php session_start(); ?> <html> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <body> <?php if (isset($_POST['login'])) { $login = $_POST['login']; if ($login == '') { unset($login);} } if (isset($_POST['password'])) { $password=$_POST['password']; if ($password =='') { unset($password);} } if (empty($login) or empty($password)) { exit ("Вы ввели не всю информацию, вернитесь назад и заполните все поля!"); } $login = mysql_real_escape_string($login); $password = mysql_real_escape_string($password); include ("settings.php"); $result = mysql_query("SELECT * FROM `users` WHERE `login` = '$login'",$db); $myrow = mysql_fetch_array($result); if (empty($myrow['password'])) { exit ("Извините, пользователя с данными ID и/или паролем не существует. <a href='index.php'>Вернуться обратно</a>"); } else { echo'<script type="text/javascript">location.replace("./index.php");</script>'; if ($myrow['password']==$password) { $_SESSION['login']=$myrow['login']; $_SESSION['id']=$myrow['id']; echo "Вы успешно вошли на сайт! <a href='index.php'>Главная страница</a>"; } else { exit ("Извините, введенные Вами данные не верны. <a href='index.php'>Вернуться обратно</a>"); } } ?> </body> </html> Что тут я делаю не так? Добавлено спустя 21 минуту 32 секунды: Ясен перец. Сначала нужно было к бд подключиться, а потом уже мацать переменные
Знаешь, я бы немного изменил логику. У тебя авторизация основана на сессиях. Я бы сделал так: Код (Text): if (!isset($_SESSION['id'])) { подключаем файл с формой авторизации } else { какие то другие действия доступные авторизованному пользователю} Далее сделал бы так: Сначала проверил в обработчике отправленные из формы пользователем данные: Код (Text): if (trim($_POST['login'])!=='') { if (trim($_POST['password'])!=='') { //Тут уже можно произвести подключение к БД и начать проверку совпадения пары логин / пароль { else { echo 'Введите пароль!'} } else { echo 'Введите логин!'; Таким же путем можно проверить на количество вводимых знаков, например чтобы юзеры не вводили логины меньше 4 символов. А на стороне клиента проверять поля с помощью Javascript, для этого к примеру хорошо подойдет jQuery Validator http://bassistance.de/jquery-plugins/jquery-plugin-validation/ Посмотри там в разделе Demo есть примеры его работы. Добавлено спустя 7 минут 40 секунд: А на счет деления пароля на две части думаю это излишне. Хотя если хочешь, то вот так это можно сделать: Код (Text): <?php $pass='1234567890'; $part1=substr($pass, 0, 3); //первые три символа $part2=substr($pass, 3); // последующие символы echo $part1.$part2; ?> Еще можешь зашифровать вдвойне md5(md5($password)) или так sha1(md5($password)) В общем методов много )))
Код (Text): <?php session_start(); ?> <html> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" > <body> <?php if (!isset($_SESSION['id'])) { if (isset($_POST['login'])) { $login = $_POST['login']; if ($login == '') { unset($login);} } if (isset($_POST['password'])) { $password=$_POST['password']; if ($password =='') { unset($password);} } if (empty($login) or empty($password)) { exit ("Вы ввели не всю информацию, вернитесь назад и заполните все поля! <a href='index.php'>Вернуться обратно</a>"); } else if((trim("$login")<>'') and (trim("$password")<>'')) { include ("settings.php"); $login=mysql_real_escape_string(trim("$login")); $password=mysql_real_escape_string(trim("$password")); $part1=substr("$password",0,2); $part2=substr("$password",2,2); $part1 = md5("fraze$part1"); $part2 = md5("fraze$part2"); $password = md5("$part1$part2"); $result = mysql_query("SELECT * FROM `users` WHERE `login` = '$login'",$db); $myrow = mysql_fetch_array($result); if ($myrow['password']=="$password") { echo'<script type="text/javascript">location.replace("./index.php");</script>'; $_SESSION['login']=$myrow['login']; $_SESSION['id']=$myrow['id']; echo "Вы успешно вошли на сайт! <a href='index.php'>Главная страница</a>"; } else { exit ("Извините, введенные Вами данные не верны. <a href='index.php'>Вернуться обратно</a>"); } } } else {echo"Вы уже авторизованы! <a href='index.php'>На главную</a>";} ?> </body> </html> Сделал все что в голову пришло. Поправьте, если что не так))