За последние 24 часа нас посетили 53240 программистов и 1768 роботов. Сейчас ищут 1284 программиста ...

Проблема с авторизацией и проверкой данных

Тема в разделе "PHP для новичков", создана пользователем Roma_SP, 4 авг 2014.

  1. Roma_SP

    Roma_SP Новичок

    С нами с:
    11 сен 2013
    Сообщения:
    89
    Симпатии:
    0
    Всем привет!Блин помогите, взломали мой сайт! Сайт простой, скорее всего просто подшутили, так как вместо данных пользователей написали всякую чушь, была скорее всего sql инъекция. Как защитить от инъекции при авторизации? И как лучше защитить страницу пользователя (т.е. личные настройки и.т.д)

    Вот код, писал не сам, просто скачал и чуть-чуть подставил свое:
    Код авторизации
    Код (Text):
    1. session_start();
    2. if (isset($_POST['login'])) { $login = $_POST['login']; if ($login == '') { unset($login);} }
    3. if (isset($_POST['password'])) { $password=$_POST['password']; if ($password =='') { unset($password);} }
    4. if (empty($login) or empty($password))
    5. {
    6. exit ("<h3><center><p style='color: #fff; background-color:#464646;'>Ошибка! Не все поля заполнены.</p></center></h3>");
    7. }
    8. $login = stripslashes($login);
    9. $login = htmlspecialchars($login);
    10. $password = stripslashes($password);
    11. $password = htmlspecialchars($password);
    12. $login = trim($login);
    13. $password = trim($password);
    14. include ("base.php");
    15. $ip=getenv("HTTP_X_FORWARDED_FOR");
    16. if (empty($ip) || $ip=='unknown') { $ip=getenv("REMOTE_ADDR"); }
    17. mysql_query ("DELETE FROM error WHERE UNIX_TIMESTAMP() - UNIX_TIMESTAMP(date) > 900");
    18. $result = mysql_query("SELECT col FROM error WHERE ip='$ip'",$db);
    19. $myrow = mysql_fetch_array($result);
    20. if ($myrow['col'] > 2) {
    21. exit ("<h3><center><p style='color: #fff; background-color:#464646;'>Вы набрали логин или пароль неверно 3 раза. Подождите 15 минут до следующей попытки.</p></center></h3>");
    22. }
    23. $password = md5($password);
    24. $password = strrev($password);
    25. $password = $password."34343vvffe";
    26.  
    27. $result = mysql_query("SELECT * FROM users WHERE login='$login' AND password='$password'",$db);
    28. $myrow = mysql_fetch_array($result);
    29. if (empty($myrow['id']))
    30. {
    31. $select = mysql_query ("SELECT ip FROM error WHERE ip='$ip'");
    32. $tmp = mysql_fetch_row ($select);
    33. if ($ip == $tmp[0]) {
    34. $result2 = mysql_query("SELECT col FROM error WHERE ip='$ip'",$db);
    35. $myrow2 = mysql_fetch_array($result2);
    36. $col = $myrow2[0] + 1;
    37. mysql_query ("UPDATE error SET col=$col,date=NOW() WHERE ip='$ip'");
    38. }
    39. else {
    40. mysql_query ("INSERT INTO error (ip,date,col) VALUES ('$ip',NOW(),'1')");
    41. }
    42. exit ("<h3><center><p style='color: #fff; background-color:#464646;'>Извините, введённый вами логин или пароль неверный.</p></center></h3>");
    43. }
    44.  
    45. echo "<html><head><meta http-equiv='Refresh' content='0; URL=page_user.php'></head></html>";
    Код на проверку в личном кабинете пользователя
    Код (Text):
    1. session_start();
    2. $db = new PDO('mysql:host=localhost;dbname=base', 'root', '');
    3. if (isset($_GET['id'])) {$id =$_GET['id']; }
    4. else
    5. { exit("<h3>Вы зашил на страницу без параметра.Вернитесь назад и заполните все данные <a href='index.php>Назад</a></h3>");}
    6. if (!preg_match("|^[\d]+$|", $id)) {
    7. exit("<p><h3>Неверный формат запроса! Проверьте URL</h3></p>");
    8. }
    9. if (!empty($_SESSION['login']) and !empty($_SESSION['password']))
    10. {
    11. $login = $_SESSION['login'];
    12. $password = $_SESSION['password'];
    13. $sqls = ("SELECT id FROM users WHERE login='$login' AND password='$password' AND activation='1'");
    14. $result = $db->query($sqls);
    15. $use = $result->fetchALL(PDO::FETCH_ASSOC);
    16. foreach ($use as $myrow2){
    17. }
    18. if (empty($myrow2['id']))
    19.    {
    20.     exit("<h3>Вход на эту страницу разрешен только зарегистрированным!!!</h3>");
    21.    }
    22. }
    23. else {
    24.  
    25. exit("<h3>Вход на эту страницу разрешен только зарегистрированным!</h3>"); }
    26.  
    27.  
    28. $sql="SELECT * FROM users";
    29. $result = $db->query($sql);
    30. $stmt = $db->prepare($sql);
    31. $stmt->execute(array(":id" => $id));
    32. $users = $result->fetchALL(PDO::FETCH_ASSOC);  
    33. foreach ($users as $myrow){
    34. }
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    об этом только ленивый не писал. НИКОГДА не подставляй в запрос сырые данные, пришедшие от пользователя.
    если это целое число — можно через intval() пропустить, если строка — mysql_real_escape_string() в твоем случае. или плейсхолдеры mysqli/pdo

    и это надо поправлять не в одном месте, а ВЕЗДЕ, где у тебя mysql_query()

    вопросы?

    Добавлено спустя 2 минуты 32 секунды:
    вот откуда ты это говно взял?
     
  3. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    А что, половина проекта на mysql, половина - на PDO?
     
  4. Roma_SP

    Roma_SP Новичок

    С нами с:
    11 сен 2013
    Сообщения:
    89
    Симпатии:
    0
    Добавлено спустя 1 минуту 51 секунду:
    То что на msql я скачал, а то что в pdo сам вставил. Думал ладно прокатит, msql не стал исправлять, сайт то не такой серьезный, но...
     
  5. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Ну вот теперь подумай заново — надо переписывать или так сойдет :)
     
  6. Roma_SP

    Roma_SP Новичок

    С нами с:
    11 сен 2013
    Сообщения:
    89
    Симпатии:
    0
    Да уж перепишу. Но в остальном есть дырки?
     
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    И еще, для общей эрудиции: HTTP_X_FORWARDED_FOR это заголовок X-Forwarder-For, который тоже приходит от пользователя (придуман чтобы цепочка прокси оставляла свой трек). Это нифига не реальный IP, его можно имитировать и использовать для атаки.

    если будешь обрабатывать все пользовательские данные перед запросом (или все пускать в плейсхолдеры), то с sql-инъекцией будет покончено. есть и другого плана угрозы. ты сделай для начала это.
     
  8. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    во-первых в формах можно поставить такой атрибут (для input, textarea и т.д.) required пока пользователь не заполнит эти поля, кнопка отправки не нажимается

    далее укорачиваем код:
    Код (PHP):
    1. if ( empty($_POST['login']) OR empty($_POST['password']) ) { // если что то все же не заполнено
    2.     exit ("<h3><center><p style='color: #fff; background-color:#464646;'>Ошибка! Не все поля заполнены.</p></center></h3>");
    3. }
    4.  
    5. $login = trim( htmlspecialchars( stripslashes( $_POST['login'] ) ) );
    6. $password = trim( htmlspecialchars( stripslashes( $_POST['password'] ) ) ); 
    ну и в том же духе перебирай весь код.
     
  9. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
  10. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    и еще я сейчас присмотрелся, но об этом уже писали выше вот это совсем не нужно - htmlspecialchars и stripslashes, все что надо делать это strip_tags
     
  11. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Ужас-ужас. VLK, ты походу не понял про какие инъекции речь. Или тупо никогда не читал доки по упомянутым функциям. Перестань тут круговорот говнокода создавать.
     
  12. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    artoodetoo уже долго пытается объяснить - не нужно удалять теги из логина, тем более заменять в нём символы на сущности html, ни то, ни другое там не мешает базе нормально обработать запрос. Всё, что надо сделать с логином перед запросом - проэкранировать. Тогда если кто-то в качестве логина введёт что-то вроде
    Код (Text):
    1. ' union truncate users; #
    или что-то в этом роде, а вашей базе будет ни горячо, ни холодно.
    Если, конечно, не используются плейсхолдеры PDO или mysqli. И не используются волшебные кавычки - уже несколько лет назад, когда я только начал работу с PHP, это считалось моветоном, так нет же - недавно попался проект, рассчитанный на то, что они включены... Доработать надо было.
     
  13. VLK

    VLK Старожил

    С нами с:
    15 дек 2013
    Сообщения:
    3.010
    Симпатии:
    58
    так ты же вроде выше писал про mysql_real_escape_string ну я и не стал повторять, зачем если уже писали, решил что то другое выискать, в частности по логике дублирование кода.