METANIT.COM

PHP safe $_GET or not

The switch thing is okay, because you are comparing against a hard-coded value (however, it’s case «show»: btw).

As @Bruce mentions in the comments, you should add a default: case as well to catch values that are not on the list, or empty values:

The second thing is potentially dangerous, as it would be possible to inject HTML and more importantly, JavaScript into the document body. You should apply a htmlspecialchars() on the variable before echoing it.

I tend to go further and validate $_GET[‘action’] against a list of expected actions, failing out if it’s not one of them

The switch will throw an error (if enabled) if ‘action’ does not exist. Checking the input against a fixed set is good, but you should also check that the parameter is passed at all in addition to adding a default case.

$_GET[‘action’] will also fail if ‘action’ does not exist. This may display errors (or stop execution), depending how PHP is configured.

The $_GET superglobal is not safe by default as it may contain special or encoded characters and other undesirable text sequences.

You can use the built in PHP function filter_input to sanitize the string according to several standard filters (see the list of filters for an idea of what is possible).

if (!($action = filter_input(INPUT_GET, 'action', FILTER_SANITIZE_STRING)))

Relies on built-in sanitize filtering, which ensures:

  • security fixes are available as PHP is patched
  • consistent/standard filtering
  • solid filter implementation (in terms of performance and security)
  • also provides a clear default case
  • syntax is a bit of a bear to remember
  • cannot use filter_input if you modify the superglobal $_GET (which you probably shouldn’t do anyway).

You could also check that the field was one of a set using in_array , which is a more dynamic method of checking if you have one of a set.

$search = in_array($search, array('show', 'hide')) ? $search : 'some-default'; 

The dynamic approach allows you to either execute or look up the target action safely, while storing the set of potential choices in a data structure versus static code.

Yes, as mentioned, you must validate the value of any $_GET variable before using it blindly. But.

You should also be checking that it even exists before using it. Depending on how you have error_reporting() set on your server, if you try to use $_GET[‘action’] and ?action=something has not been specified in the URL then you’ll get an E_NOTICE — Undefined index : action, which will either pollute your error logs or worse, appear in the browser.

$urlAction = isset($_GET['action']) ? $_GET['action'] : null; if (isset($urlAction)) < // Rest of validation. >

Источник

Безопасный get запрос php

Большое значение в PHP имеет организация безопасности данных. Рассмотрим несколько простых механизмов, которые могут повысить безопасность нашего веб-сайта.

Но вначале возьмем форму из прошлой темы:

      if(isset($_POST["age"])) < $age = $_POST["age"]; >echo "Имя: $name 
Возраст: $age"; ?>

Форма ввода данных

Имя:

Возраст:

И попробуем ввести в нее некоторые данные. Например, введем в поле для имени ««:

Читайте также:  Echo html content in php

Безопасность в PHP

После отправки данных в html разметку будет внедрен код javascript, который выводит окно с сообщением.

Это относительно простой и безвредный скрипт. Однако внедряемый код может быть более вредоносным. И чтобы избежать подобных проблем с безопасностью, рекомендуется применять функцию htmlentities() . В качестве параметра она принимает значение, которое надо экранировать:

$name = "не определено"; $age = "не определен"; if(isset($_POST["name"])) < $name = htmlentities($_POST["name"]); >if(isset($_POST["age"])) < $age = htmlentities($_POST["age"]); >echo "Имя: $name 
Возраст: $age";

И даже после ввода кода html или javascript все теги будут экранированы, и мы получим следующий вывод:

Функция htmlentities в PHP

Еще одна специальная функция — htmlspecialchars() похожа по действию на htmlentities :

$name = "не определено"; $age = "не определен"; if(isset($_POST["name"])) < $name = htmlspecialchars($_POST["name"]); >if(isset($_POST["age"])) < $age = htmlspecialchars($_POST["age"]); >echo "Имя: $name 
Возраст: $age";

Еще одна функция — функция strip_tags() позволяет полностью исключить теги html:

$name = "не определено"; $age = "не определен"; if(isset($_POST["name"])) < strip_tags($_POST["name"]); >if(isset($_POST["age"])) < strip_tags($_POST["age"]); >echo "Имя: $name 
Возраст: $age";

Результатом ее работы при том же вводе будет следующий вывод:

Источник

Безопасность в PHP (Обработка даных полученных от пользователей)

Всегда проверяйте полученные данные от пользователя ($_POST, $_GET, $_REQUEST, $_COOKIE, $_FILES) , причем не только от разных инъекций, XSS и прочего, но и на корректность вводимых данных, например, если у вас интернет магазин, то проверяйте, чтобы количество товаров было не отрицательным и целым.

Представьте себя на месте хакера, подумайте чтобы вы сделали с сайтом.

SQL-инъекции

  • mysql_escape_string() — для защиты строк и двоичных данных
  • mysql_real_escape_string() — для защиты строк и двоичных данных в соответствии с кодировкой, установленной на сервере (требуется соединение с сервером, иначе возвращает пустой результат)
  • intval() — для защиты целочисленных цифровых значений, intval() возвращает 0 в случае если строка не число.
  • floatval() — для защиты дробных значений, аналогичное поведение как и у intval()

XSS

PHP-инъекция

PHP-инъекция (англ. PHP injection) — один из способов взлома веб-сайтов, работающих на PHP, заключающийся в выполнении постороннего кода на серверной стороне. Читать дальше на wikipedia

Это способ взлома, когда можно исполнить любой php-код на стороне сервера, Очень наспространен благодаря функции include(), в которую новички передают перерменную, полученную от пользователя. Ошибочно думают, что код include($_GET[‘file’].».php»); спасает от такой инекции. НО ЭТО ОШИБКА. Потому что злоумышленник может передать в переменную file «ya.ru/%00»(без ковычек) что отбросит расширение .php

  • addslashes() — она экранирует NULL-символ(в html он обозначется как %00), слеш и ковычки, что позволяет избавиться от нежелательных инъекций, но лучше пользоваться оператором switch, например:

Заключение

Здесь я описал общие принципы, которыми пользуюсь я. Буду рад, если вы поможите дополнить эту статью.

Источник

Защита GET параметров

Привет.Помогите новичку. Подскажите как правильно проверять и защищать GET-параметры? Припустим они отправляются по нажатию на ссылку:

    защитаphp
)" data-controller="se-share-sheet" data-se-share-sheet-title="Поделиться ссылкой на вопрос" data-se-share-sheet-subtitle="" data-se-share-sheet-post-type="question" data-se-share-sheet-social="facebook twitter " data-se-share-sheet-location="1" data-se-share-sheet-license-url="https%3a%2f%2fcreativecommons.org%2flicenses%2fby-sa%2f3.0%2f" data-se-share-sheet-license-name="CC BY-SA 3.0" data-s-popover-placement="bottom-start">Поделиться
)" title="">Улучшить вопрос
)">изменён 13 окт 2012 в 20:58
задан 13 окт 2012 в 16:40
6
    1
    Люди люди! Что вы делаете! Нельзя передавать явно ГЕТ в ссылках! Нет нет и нет. Используйте ЧПУ!
    – stck
    13 окт 2012 в 19:46
    1
    @stk можно, если проверять все принимаемые параметры на допустимость. Да и ЧПУ не делает код безопасным. Безопасным его опять же делает проверка всего что приходит от пользователя.
    – ReinRaus
    13 окт 2012 в 20:20
    @ReinRaus, пускай они даже будут верными и допустимые но ссылки вида ссылка не годятся. Всю дрянь в post или ещё куда. Это плохая привычка - ухудшает восприятие и юзабельность
    – stck
    13 окт 2012 в 20:28
    Пользователям все равно используете Вы ЧПУ или нет, ничего не ухудшиться. Это хорошо для SEO, когда адрес отражает суть страницы, а пользователю и человеку который ищет уязвимости все равно.
    – ReinRaus
    13 окт 2012 в 20:43
    Спасибо вам за коментарии
    – koza4ok
    13 окт 2012 в 20:53
|Показать ещё 1 комментарий

3 ответа 3

Сброс на вариант по умолчанию
7

через get параметры можно можно и базу своровать, имея лишь прямые руки. Так что постоянно нужно проверять вводимые значения. Я зачастую использую эти три функции при очистке параметров GET и POST:

$str = $_GET['параметр']; $str = trim($str); $str = stripslashes($str); $str = htmlspecialchars($str);

После получаю безопасную строку, которую уже сравниваю. Если она должна быть только числовой, то проверяю на is_numeric() и так далее. В вашем случае можно использовать то что я написал выше, а еще проверить строку на максимальную длину. Наверное у Вас name может быть не более 15 символов(к примеру). Так что проверяйте и на это. Потом проверяйте на иные символы с помощью preg_match. То же самое и с POST запросами. У меня в проекте даже функция отдельная есть:

Источник

PHP $_GET security, $_POST security best practice

At the moment I xss_clean, and strip_tags. I've always done this, just by autopilot. Is there a better technique? Apologies if there's an identical question out there. I kinda assume there is, although I couldn't find one as thorough as this.

4 Answers 4

  1. Use the appropriate function while outputting, in HTML context, this is htmlspecialchars
  2. Use prepared statements
  3. See 1. and 2. – depending on whether you are displaying the variable or you are using it in a query.

There is currently a buffer overflow in PHP 5.4 htmlspecialchars,htmlentities. fortiguard.com/encyclopedia/vulnerability/…

And use ENT_QUOTES as the second parameter for htmlspecialchars() if you output a string in an input value attribute and if you use single quotes.

This knowledge on htmlspecialchars is great. Thanks. Can you elaborate further on "used prepared statements?" I'm primarily using mysql, so is mysql_real_escape_string good enough?

One of worst delusions in the PHP world is that $_GET or $_POST have anything to do with security.

It is not the source but destination that matters

  • If you have to deal with database, the rules always the same, no matter if the data is coming from $_POST , SOAP request or a database. It has to be ALWAYS the same: placeholders for the data, whitelisting for the everything else.
  • If you have to output some data into browser, you have to properly prepare it, no matter whether the data is coming from $_POST , SOAP request or a database.
  • If you have to read from a file - you have to secure the filename, no matter where it coming from, and so on

Erm, yes. I clearly ask for a solution to both input types, implying that there is no differentiation.

@Michael please read my answer attentively. You don't need no special security for the POST.You need it for the database. Don't you understand that?

Thanks for your answer. You were a deadly combination of helpful and angry, like a college professor in the midst of a divorce. I do understand that the source is irrelevant, and sorry if I didn't make that clear. Your other points throughout this question are good, and I've cleared a lot up in my mind. I'm largely using CI & active record classes, so this is largely educational for me, just make sure I totally understand what's happening in my applications. Thanks again.

  1. In the first case htmlspecialchars() probably is the best choice, allowing for users to use all characters like , &, etc.
  2. In the second case you will need to use some database escaping function like mysql_real_escape_string or a prepared statement with PDO or mysqli. Prepared statements are the best choice here but if you are only familiar with mysql then mysql_real_escape_string works fine too. If you are not using mysql then there are similar functions in most SQL APIs.
  3. In the third case do both but separately, with gives you two diffrent results, one for output and one for database.

escaping has nothing to do with security. mysql_real_escape_string IS NOT works fine. -1. Shame to one who upvoted.

Well yes it does, if you do not properly escape data sent to databases like MySQL and such you will leave it vulnerable to SQL injections. This is also true for outputted data in HTML which will be vulnerable to XSS attacks if you do not escape/encode the output properly.

$id="1;drop table users;"; $id=mysql_real_escape_string($id); $sql="SELECT * FROM table WHERE > eat it

I get your point, but you made the mistake of escaping something which was not sent as a string. It would however work if you sent it as a string. It is a crude way to do it and one should of course always validate integers with is_numeric and intval but if you instead used mysql_real_escape_string and wrapped your id in quotation marks, thus sending it as a string, MySQL would ignore the extra data in the id (;drop table users;) and just fetch you the row with id 1. SELECT * FROM table WHERE table users;"

It is not my mistake but yours. There is nothing in your answer about strings. And even if there was, change the query to $sql="SELECT * FROM table LIMIT $id"; and try to excuse yourself again.

Источник

Оцените статью