Всем привет!Блин помогите, взломали мой сайт! Сайт простой, скорее всего просто подшутили, так как вместо данных пользователей написали всякую чушь, была скорее всего sql инъекция. Как защитить от инъекции при авторизации? И как лучше защитить страницу пользователя (т.е. личные настройки и.т.д) Вот код, писал не сам, просто скачал и чуть-чуть подставил свое: Код авторизации Код (Text): session_start(); 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 ("<h3><center><p style='color: #fff; background-color:#464646;'>Ошибка! Не все поля заполнены.</p></center></h3>"); } $login = stripslashes($login); $login = htmlspecialchars($login); $password = stripslashes($password); $password = htmlspecialchars($password); $login = trim($login); $password = trim($password); include ("base.php"); $ip=getenv("HTTP_X_FORWARDED_FOR"); if (empty($ip) || $ip=='unknown') { $ip=getenv("REMOTE_ADDR"); } mysql_query ("DELETE FROM error WHERE UNIX_TIMESTAMP() - UNIX_TIMESTAMP(date) > 900"); $result = mysql_query("SELECT col FROM error WHERE ip='$ip'",$db); $myrow = mysql_fetch_array($result); if ($myrow['col'] > 2) { exit ("<h3><center><p style='color: #fff; background-color:#464646;'>Вы набрали логин или пароль неверно 3 раза. Подождите 15 минут до следующей попытки.</p></center></h3>"); } $password = md5($password); $password = strrev($password); $password = $password."34343vvffe"; $result = mysql_query("SELECT * FROM users WHERE login='$login' AND password='$password'",$db); $myrow = mysql_fetch_array($result); if (empty($myrow['id'])) { $select = mysql_query ("SELECT ip FROM error WHERE ip='$ip'"); $tmp = mysql_fetch_row ($select); if ($ip == $tmp[0]) { $result2 = mysql_query("SELECT col FROM error WHERE ip='$ip'",$db); $myrow2 = mysql_fetch_array($result2); $col = $myrow2[0] + 1; mysql_query ("UPDATE error SET col=$col,date=NOW() WHERE ip='$ip'"); } else { mysql_query ("INSERT INTO error (ip,date,col) VALUES ('$ip',NOW(),'1')"); } exit ("<h3><center><p style='color: #fff; background-color:#464646;'>Извините, введённый вами логин или пароль неверный.</p></center></h3>"); } echo "<html><head><meta http-equiv='Refresh' content='0; URL=page_user.php'></head></html>"; Код на проверку в личном кабинете пользователя Код (Text): session_start(); $db = new PDO('mysql:host=localhost;dbname=base', 'root', ''); if (isset($_GET['id'])) {$id =$_GET['id']; } else { exit("<h3>Вы зашил на страницу без параметра.Вернитесь назад и заполните все данные <a href='index.php>Назад</a></h3>");} if (!preg_match("|^[\d]+$|", $id)) { exit("<p><h3>Неверный формат запроса! Проверьте URL</h3></p>"); } if (!empty($_SESSION['login']) and !empty($_SESSION['password'])) { $login = $_SESSION['login']; $password = $_SESSION['password']; $sqls = ("SELECT id FROM users WHERE login='$login' AND password='$password' AND activation='1'"); $result = $db->query($sqls); $use = $result->fetchALL(PDO::FETCH_ASSOC); foreach ($use as $myrow2){ } if (empty($myrow2['id'])) { exit("<h3>Вход на эту страницу разрешен только зарегистрированным!!!</h3>"); } } else { exit("<h3>Вход на эту страницу разрешен только зарегистрированным!</h3>"); } $sql="SELECT * FROM users"; $result = $db->query($sql); $stmt = $db->prepare($sql); $stmt->execute(array(":id" => $id)); $users = $result->fetchALL(PDO::FETCH_ASSOC); foreach ($users as $myrow){ }
об этом только ленивый не писал. НИКОГДА не подставляй в запрос сырые данные, пришедшие от пользователя. если это целое число — можно через intval() пропустить, если строка — mysql_real_escape_string() в твоем случае. или плейсхолдеры mysqli/pdo и это надо поправлять не в одном месте, а ВЕЗДЕ, где у тебя mysql_query() вопросы? Добавлено спустя 2 минуты 32 секунды: вот откуда ты это говно взял?
Добавлено спустя 1 минуту 51 секунду: То что на msql я скачал, а то что в pdo сам вставил. Думал ладно прокатит, msql не стал исправлять, сайт то не такой серьезный, но...
И еще, для общей эрудиции: HTTP_X_FORWARDED_FOR это заголовок X-Forwarder-For, который тоже приходит от пользователя (придуман чтобы цепочка прокси оставляла свой трек). Это нифига не реальный IP, его можно имитировать и использовать для атаки. если будешь обрабатывать все пользовательские данные перед запросом (или все пускать в плейсхолдеры), то с sql-инъекцией будет покончено. есть и другого плана угрозы. ты сделай для начала это.
во-первых в формах можно поставить такой атрибут (для input, textarea и т.д.) required пока пользователь не заполнит эти поля, кнопка отправки не нажимается далее укорачиваем код: Код (PHP): if ( empty($_POST['login']) OR empty($_POST['password']) ) { // если что то все же не заполнено exit ("<h3><center><p style='color: #fff; background-color:#464646;'>Ошибка! Не все поля заполнены.</p></center></h3>"); } $login = trim( htmlspecialchars( stripslashes( $_POST['login'] ) ) ); $password = trim( htmlspecialchars( stripslashes( $_POST['password'] ) ) ); ну и в том же духе перебирай весь код.
и еще я сейчас присмотрелся, но об этом уже писали выше вот это совсем не нужно - htmlspecialchars и stripslashes, все что надо делать это strip_tags
Ужас-ужас. VLK, ты походу не понял про какие инъекции речь. Или тупо никогда не читал доки по упомянутым функциям. Перестань тут круговорот говнокода создавать.
artoodetoo уже долго пытается объяснить - не нужно удалять теги из логина, тем более заменять в нём символы на сущности html, ни то, ни другое там не мешает базе нормально обработать запрос. Всё, что надо сделать с логином перед запросом - проэкранировать. Тогда если кто-то в качестве логина введёт что-то вроде Код (Text): ' union truncate users; # или что-то в этом роде, а вашей базе будет ни горячо, ни холодно. Если, конечно, не используются плейсхолдеры PDO или mysqli. И не используются волшебные кавычки - уже несколько лет назад, когда я только начал работу с PHP, это считалось моветоном, так нет же - недавно попался проект, рассчитанный на то, что они включены... Доработать надо было.
так ты же вроде выше писал про mysql_real_escape_string ну я и не стал повторять, зачем если уже писали, решил что то другое выискать, в частности по логике дублирование кода.