Авг 282013
 

Безопасность в PHP. Проверяем типы переменных.

Известно, что PHP относится к слабо типизированным языкам программирования. Что же это значит? Мы можем проводить различные операции между переменными разного типа, и получать «что-то» на выходе. С одной стороны, это удобно. Строка превращается в целое число, целое число может стать объектом, а объект плавно перейти в массив. Но любой программист при создании сайтов на языке php рано или поздно сталкивается с тем, что во многих случаях типы переменных следует приводить (или, как минимум, проверять перед началом использования).

Примечание: такое строгое отношение к переменным связано с тем, что большинство скриптов на php подвержено нездоровому вниманию злоумышленников с целью подстановки параметров различного типа в строке запроса сайта. Это может привести от генерации ошибки с раскрытием пути, по которому находится файл, вплоть до обхода некоторых ограничений. Например: повышения прав пользователя в ранних версиях WordPress путём передачи имени пользователя как массива, а не строки, в скрипт аутентификации в admin панели, или же подстановки в строку запроса вместо целых чисел (например, id новости) – специально сформированных запросов sql с целью несанкционированного доступа, создание на сайте так называемых sql инъекций.

Так что, по возможности, проверяйте типы переменных перед их использованием или явно приводите их во время программирования на PHP.

Приведём функции, которые будут нам полезны с целью контроля безопасности входных данных:

(string) trim($str) – Принимаемые параметры: $var – строка для удаления пробельных символов и символов разрыва строки. Обрезает символы конца строки и пробельные символы вначале и конце строки, возвращает переменную строкового типа.
(bool) is_string($var) — Принимаемые параметры: $var – переменная для проверки. Является ли переменная $var строкой? Возвращает: true: если является, false: если не является.
(bool) is_numeric($var) – Принимаемые параметры: $var – переменная для проверки. Является ли переменная $var набором цифр ? Возвращает: true: если является, false: если не является.
(bool) is_float($var) — Принимаемые параметры: $var – переменная для проверки. Является ли переменная $var вещественным числом? Возвращает: true: если является, false: если не является.
(bool) is_array($var) — Принимаемые параметры: $var – переменная для проверки. Является ли переменная $var массивом? Возвращает: true: если является, false: если не является.
(bool) is_int($var) — Принимаемые параметры: $var – переменная для проверки. Является ли переменная $var целым числом? Возвращает: true: если является, false: если не является.
(bool) isset($var) – Принимаемые параметры: $var – переменная для проверки. Проверяет, существует ли переменная $var (любой тип данных), если существует, возвращает true, иначе возвращает false.
(bool) is_resource($var) – Принимаемые параметры: $var – переменная для проверки. Является ли переменная $var ресурсом? Возвращает: true: если является, false: если не является.
(bool) empty($var) — Принимаемые параметры: $var – переменная для проверки. Проверяет, пуста ли существующая переменная или нет, возвращаемые значения: true для значений («», 0, 0.0, «0», NULL,FALSE,array()), false в остальных случаях
Пример использования при программировании в PHP скриптах:

Передаем в форму через пост запрос массив данных $user, полученный при регистрации пользователя:

<?php
        $user               = $_POST["user"];
        $sizeof             = sizeof($user);
        $username           = "";
        $password           = "";
        $user_id            = 0;
if(is_array($user) && $sizeof && isset($user["username"]) && isset($user["password"];)){
        $username           = trim($user["username"]);
        $password           = trim($user["password"]);
        $password           = is_int($user["user_id"]) ? $user["user_id"]: 0;
}
?>

Еще один пример использования в PHP скриптах:

Зададим вопрос к базе данных:

<?php
        $query              = "SELECT `news_text` FROM `news` WHERE `news_id`=5";
        $p                  = mysql_query($query);
        if($p && is_resource($p)){
            list($news_text)= mysql_fetch_row($p);
        }
?>

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

Авг 282013
 

Безопасность в PHP. Явное приведение типов.

Операторы прямого приведения данных.

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

Приведём несколько операндов, которые позволяют сделать это легко и без особых усилий при программировании на языке PHP, а так же поговорим о функциях приведения типов.

Примечание автора: операторы не изменяют тип переменной, но делает попытку приведения переменной и возвращает значение соответствующего типа.

$var = (int)$some_var, (integer)$some_var – явное приведение переменной $some_var к целочисленному типу
$var = (float)$some_var, (real)$some_var, (double)$some_var – явное приведение переменной $some_var к вещественному типу
$var = (array)$some_var – явное приведение переменной $some_var к массиву
$var = (string)$some_var – явное приведение переменной $some_var к массиву
$var = (bool)$some_var, (boolean)$some_var – явное приведение переменной $some_var логическому значению (true,false)
$var = (object)$some_var – явное приведение переменной $some_var к объекту
Новшества PHP 5:

(unset)$some_var – присвоение типа NULL, уничтожение переменной, освобождение памяти.
Новшества PHP 5.2.1:

(binary) $some_var – приведение переменной к бинарному представлению.
Примеры использования:

Рассмотрим передачу id статьи через массив GET news.php?id=23

Вариант подготовки параметра для безопасной передачи в запрос к базе данных:

?
1
$news_id = (int)$_GET[«id»];
Еще одной интересной функцией является abs, которую советую применять при фильтрации входных данных для заведомо неотрицательных величин, например уникального идентификатора статьи, который является по умолчанию числом уникальным, положительным, с auto increment:

abs($var) – Принимаемые параметры: $var – переменная целого (или вещественного) типа. Возвращает абсолютное по модулю число: для всех отрицательных величин возвращается положительное, для всех положительных возвращается просто значение переменной

Рассмотрим предыдущий пример в новом ракурсе:

Так как integer может быть как положительным, так и отрицательным целым числом, перепишем предыдущий пример с использованием функции abs:

Вариант подготовки параметра для безопасной передачи в запрос к базе данных:

?
1
$news_id = abs((int)$_GET[«id»]);
Функции явного приведения данных.

(int) intval($var,[$base = 10]) — Принимаемые параметры: $var – переменная для приведения типов. Приводит переменную к целочисленному типу. Возвращает переменную, приведенную к целочисленному типу, в случае с массивом 0 если массив пуст, 1 – если есть элементы, в случае со строкой: если удаётся преобразовать к целому числу – то целое число, или 0 в обратном случае.

$base = основание, десятичная система исчисления по умолчанию.

(float) floatval($var) — Принимаемые параметры: $var – переменная для приведения типов. Приводит переменную к вещественному типу. Возвращает переменную, приведенную к вещественному типу, в случае неудачи возвращает 0.
(bool) settype(&$var, string $type ) — Принимаемые параметры: $var – переменная для приведения типов, $type – к какому типу привести переменную:

«boolean»,»bool» – приведение типа переменной к логическому значению (true, false),
«integer»,»int» – приведение типа переменной к целому значению,
«float»,»double» – приведение типа переменной к вещественному значению,
«string» – приведение типа переменной к строковому значению,
«array» – приведение к массиву,
«object» – приведение типа переменной к объекту,
«null» – приведение типа переменной к типу NULL (освобождение занимаемой памяти).
Производит прямое приведение переменной к значению указанного типа. В случае удачи возвращает true, иначе – false.

Общирный пример практического использования вышеописанных функций при программировании на языке PHP:

Приведём пример безопасного запроса к базе данных с получением id новости из строки запроса:

<?php
$id             = isset($_GET["id"]) ? abs(intval($_GET["id"])) : 0;
If(!empty($id)){
    $q          = "SELECT `news_text` FROM `news` WHERE `news_id`=".$id;
    $p          = mysql_query($q);
    if($p && is_resource($p)){
    list($text) = mysql_fetch_row($p);
    echo $text;
}
}
?>