За последние 24 часа нас посетили 17507 программистов и 1716 роботов. Сейчас ищут 1789 программистов ...

Защита от MYSQL иньекций

Тема в разделе "PHP для новичков", создана пользователем Колбася, 11 ноя 2012.

  1. Колбася

    Колбася Активный пользователь

    С нами с:
    12 дек 2011
    Сообщения:
    722
    Симпатии:
    0
    Привет ребята!
    Есть вот такое -
    Код (PHP):
    1. $tar = mysql_fetch_array(mysql_query("SELECT * FROM `users` WHERE `login` = '{$_POST['target']}' LIMIT 1;"));  
    Я где-то слышал что если делать так, то есть риск получить иньекцию, подскажите как это исправить?
    Говорят есть mysql-real-escape-string
    Это будет выглядеть так -
    Код (PHP):
    1. $_POST['target'] =mysql_real_escape_string($_POST['target']);
    2. $tar = mysql_fetch_array(mysql_query("SELECT * FROM `users` WHERE `login` = '{$_POST['target']}' LIMIT 1;"));  
    ?
     
  2. vikrorpert

    vikrorpert Активный пользователь

    С нами с:
    13 окт 2010
    Сообщения:
    984
    Симпатии:
    10
    использовать PDO
     
  3. jenya777777

    jenya777777 Активный пользователь

    С нами с:
    16 мар 2010
    Сообщения:
    562
    Симпатии:
    0
    используй фильтры filter_var
     
  4. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    правильная защита для pdo или mysqli - плейсхолдеры. для mysql - mysql_real_escape
     
  5. Колбася

    Колбася Активный пользователь

    С нами с:
    12 дек 2011
    Сообщения:
    722
    Симпатии:
    0
    А я правильно переписал?
     
  6. Gold Dragon

    Gold Dragon Активный пользователь

    С нами с:
    30 сен 2012
    Сообщения:
    306
    Симпатии:
    2
    Адрес:
    Тамбов
    это не защита от инъекций, а просто экранирование
    а вообще, всё что приходит от пользователя нужно проверять и простого экранирования может не хватить

    Добавлено спустя 59 секунд:
    Код (PHP):
    1.     $target =mysql_real_escape_string($_POST['target']);
    2.     $tar = mysql_fetch_array(mysql_query("SELECT * FROM `users` WHERE `login` = ' . $target . ' LIMIT 1;"));   
     
  7. Колбася

    Колбася Активный пользователь

    С нами с:
    12 дек 2011
    Сообщения:
    722
    Симпатии:
    0
    Это получается целый обработчик делать потом сдевить его глобал по сайту и во всех постах предпроверка будет с ним?
     
  8. Gold Dragon

    Gold Dragon Активный пользователь

    С нами с:
    30 сен 2012
    Сообщения:
    306
    Симпатии:
    2
    Адрес:
    Тамбов
    тебе нужна безопасность или "простенький код"?
    Сделай отдельный класс, в котором просто и проверяй определённые типы по своим правилам. Ну или воспользуйся filter_var()

    Например, у меня (если не считать HTML-код) процентов 60-70 от всего кода - это проверка на безопасность
     
  9. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    экранирование это защита от sql-инъекций, необходимая и достаточная.

    давай не путать мух с супом. "проверять данные" это более общая задача.

    чтобы случайно не забыть экранировать строки, имеет смысл перейти на prepared statesment — это тру вэй. ну а если почему-то хочется остаться на интерфейсе mysql (не mysqli и не pdo mysql), то было бы неплохо написать свой симулятор плейсхолдеров, работающий с mysql_real_escape_string().

    Добавлено спустя 41 минуту 42 секунды:
    Если быть совсем честным, то есть трудности в сочетании mysql_real_escape_string() и mysql_query('set names utf8').
    Некоторые зловредные многобайтовые символы неправильно экранируются и могут быть использованы для атаки.

    Описано, например, здесь: http://stackoverflow.com/questions/1220182/does-mysql-real- ... -injection
    Проблема происходит от того, что эскейпинг не знает, что мы решили использовать мультибайтную UTF-8, наш 'set names utf8' проходит для него незамеченным :(
    Выход: переключение на utf-8 через вызов mysql_set_charset(), тогда все всё знают и умеют правильно экранировать.

    Это НЕ значит, что экранирование недостаточная мера. Это значит, что надо правильно всё настраивать.
    PHP. Character sets
     
  10. jenya777777

    jenya777777 Активный пользователь

    С нами с:
    16 мар 2010
    Сообщения:
    562
    Симпатии:
    0
    Для удобного использования плэйсхолдеров можешь воспользоваться библиотекой DBSimple, там все это реально просто реализовано.
     
  11. Gold Dragon

    Gold Dragon Активный пользователь

    С нами с:
    30 сен 2012
    Сообщения:
    306
    Симпатии:
    2
    Адрес:
    Тамбов
    Вот только наоборот. И экранирование это не защита(!). Это просто экранирование спецсимволов. А если я передаю строку где нет спецсимволов? Это большое заблуждение когда народ считает что экранированием спасётся от инъекций... Экранирование это чтобы запрос не посыпался при обработке

    Самый простейший пример из ВИКИ
    Передаём через POST значение ID '-1 OR 1=1';
    и мы получаем запрос
    Код (Text):
    1. SELECT login, password FROM user WHERE id = $_POST['id']
    т.е.
    Код (Text):
    1. SELECT login, password FROM user WHERE id = -1 OR 1=1
    Т.е. хоть об экранируйся, но получим мы все пароли и логины из базы

    Добавлено спустя 2 минуты 59 секунд:
    не в качестве рекламы, но я уже предлагал в подобных случаях свой класс... )) Он современнее DBSimple и развивается =)
    https://github.com/GoDr/GDLDatabase
     
  12. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    LOL. это пример корявой логики программиста, а не ущербности функции экранирования.

    в общем случае, если ты экранируешь строку, ты подразумеваешь, что это СТРОКА. значит запрос наверное содержит строку в апострофах:
    Код (PHP):
    1. mysql_query("SELECT login, password FROM user WHERE id = '{$id}'"); // у нас здесь строка -- В АПОСТРОФАХ    
    оно, кстати, не вызовет ошибки, даже если поле id целое :)
    пожалуйста, попробуй подсунуть сюда инъекцию. сумеешь — я тебе куплю пиво, обещаю!

    или, если мы работаем с id как с целым, без апострофов:
    Код (PHP):
    1. $id = intval($id);
    2. mysql_query("SELECT login, password FROM user WHERE id = {$id}"); // у нас здесь целое    
    это правильная логика

    Добавлено спустя 5 минут 34 секунды:
    это был "ручной" способ.
    а плейсхолдеры (те которые "родные") сами понимают где строка, а где не строка. если мы реализуем свою функцию плейсхолдеров, мы должны добавить простую логику типа:
    Код (PHP):
    1. $id = is_string($id) ? ("'" . mysql_real_escape_string($id) ."'") : (is_null($id) ? 'NULL' : $id);
    2.  
     
  13. jenya777777

    jenya777777 Активный пользователь

    С нами с:
    16 мар 2010
    Сообщения:
    562
    Симпатии:
    0
    Хотел почитать документацию по твоему классу, но к сожалению там не открываются ссылки ни какие. =(
     
  14. Gold Dragon

    Gold Dragon Активный пользователь

    С нами с:
    30 сен 2012
    Сообщения:
    306
    Симпатии:
    2
    Адрес:
    Тамбов
    Вот видишь , ты сам к этому пришёл :) Экранирование - это экранирование... И все данные нужно готовить...

    Это я привёл самый простейший пример, что такое вообще может иметь место... А если смотреть сам вопрос темы, то такое может иметь место т.к. глобальное значение просто тупо вставлено в запрос =)

    А инъекции могут быть очень и очень навороченные, и даже предусматривающие экранирование.

    В итоге мы приходим с чего я начал.. ID - это integer, а следовательно $_POST[id] нужно к этому привести

    Добавлено спустя 1 минуту 6 секунд:
    ВИКИ пока не доступна
    самая полная документация тут
    http://forum.vingrad.ru/index.php?showtopic=357736&view=findpost&p=2528484
     
  15. Your

    Your Старожил

    С нами с:
    2 июл 2011
    Сообщения:
    4.074
    Симпатии:
    7
  16. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    Gold Dragon, мы с тобой видимо в разных реальностях живем. на моем русском языке фраза
    "экранирование это защита от sql-инъекций, необходимая и достаточная."
    понимается однозначно. никакая логика программы не отменяет нужности и не доказывает беспомощности экранирования.

    не надо демагогии, я вас умоляю.
     
  17. Gold Dragon

    Gold Dragon Активный пользователь

    С нами с:
    30 сен 2012
    Сообщения:
    306
    Симпатии:
    2
    Адрес:
    Тамбов
    да без проблем. даже и не собирался. Просто для моих проектов этого мало =)

    А чтобы завершить эту тему, достаточно просто двух цитат из официальных источников
    ;)
     
  18. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    то есть ты согласился с экранированием? или мы опять видим разное? )))
     
  19. Gold Dragon

    Gold Dragon Активный пользователь

    С нами с:
    30 сен 2012
    Сообщения:
    306
    Симпатии:
    2
    Адрес:
    Тамбов
    Мы видим абсолютно одинаково, только для меня экранирование это БОЛЬШОЙ плюс при борьбе с инъекциями, но это не панацея.
    С другой стороны, я уже полностью перешёл на MySQLi и подготовленные выражения, так что экранирование так каковое для меня это что-то древнее =)

    PS
    есть у меня такая не хорошая черта - навязать своё мнение и оставить последнее слово за собой ))) но я активно борюсь с этим.. Хотя этот чуждо только для бесхарактерных ))))
     
  20. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    peace! не один ты работаешь над собой )
     
  21. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    можете привести КОНКРЕТНЫЙ пример, когда экранирование пропустит инъекцию?
     
  22. Gold Dragon

    Gold Dragon Активный пользователь

    С нами с:
    30 сен 2012
    Сообщения:
    306
    Симпатии:
    2
    Адрес:
    Тамбов
    выше уже написал
     
  23. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    фигня. притянуто за уши.
    значения в кавычки кто будет брать? это даже не хороший тон а синтаксис SQL.
    Код (PHP):
    1. $_POST['id'] = '-1 OR 1=1';
    2. $sql = "SELECT login, password FROM user WHERE id ='".mysql_escape_string($_POST['id'])."' ";
    3. echo $sql;// SELECT login, password FROM user WHERE id ='-1 OR 1=1'  
    и никаких паролей из БД ты неполучишь!
     
  24. Gold Dragon

    Gold Dragon Активный пользователь

    С нами с:
    30 сен 2012
    Сообщения:
    306
    Симпатии:
    2
    Адрес:
    Тамбов
    да чтож такое то... я не собираюсь писать реальные запросы и что-то доказывать.. Просто привёл пример что такое возможно =)
     
  25. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    да тут нечего доказывать.
    mysql_escape_string() экранирует данные делая их(для БД) - данными, а не управляющими конструкциями.
    если в рамках запроса данные обнесены кавычками, то никакие инъекции не пролезут.