RSS   Twitter   Copiny   Copiny
Нашел ошибку? 

Выдели фрагмент текста с ошибкой или неточностью и нажми Ctrl+Enter!

Безопасные SQL запросы

SQL-инъекция (SQL injection) — один из способов взлома сайтов, работающих с использованием SQL баз данных. Используется внедрение своего SQL-кода. Этот тип атак на сайты один из самых популярных в сети интернет. Последствий атаки с использованием инъекций могут быть непоправимы. Обычно атаки подобного рода направлены на то чтобы получить доступ к базе данных, учетным записям и так далее, но так же возникает огромная угроза полного уничтожения базы данных, что приведет его к нерабочему состоянию.

Преодоление последствий нападения инъекции SQL это одно, но предотвращение их это совершенно другое. Этот статья объясняет, каким образом мы можем обеспечить безопасность на сайте Joomla, с использованием Framework Joomla. Для получения дополнительной информации о инъекции SQL, обратитесь к CWE-89.


Для начала просто получим ссылку на глобальный объект Joomla отвечающий за базу данных сайта Joomla.

$db = JFactory::getDBO();

Существует два основных метода обращения к записям из таблицы MySQL:

  • По идентификаторам и именам
  • По строковым значениям

Метод JDatabase::nameQuote() - используется для безопасного представления идентификаторов и имен. Для начала мы это продемонстрируем на простом примере с одним идентификатором:

$name = $db->nameQuote('columnIdentifier');

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

// Подготавливаем идентификаторы
$tableIdentifier  = $db->nameQuote('tableIdentifier');
$columnIdentifier = $db->nameQuote('columnIdentifier');

// Создаем полное имя
$name = "$tableIdentifier.$columnIdentifier";

Теперь разберем выборки с использованием слов как идентификаторов. В MySQL все строковые значения должны обрамляться одинарной либо двойной кавычкой. Вроде в этом нет никаких сложностей, до тех пор пока наша строка не будет содержать эти кавычки как часть себя. с помощью метода JDatabase::Quote() мы больше можем не обращать внимание на тексты подобного рода. Например:

$tableIdentifier  = $db->nameQuote('tableIdentifier');
$columnIdentifier = $db->nameQuote('columnIdentifier');
$sql = "SELECT * FROM $tableIdentifier " 
     . "WHERE $columnIdentifier "
     . ' = ' . $db->Quote("How's the recipe\book going?");

Метод JDatabase::Quote() просто с учетом текущего типа базы данных экранирует нежелательные символы в итоге из строки

How's the recipe\book going?

получаем следующее

'How\'s the recipe\\book going?'

Текст окружен кавычками и все спец символы экранированы.

Обратиться к записи можно не только по словам, но и числам как целым так и с плавающей запятой. Для проверки обычно используется функции int, intval, (float), floatval. Использование в примере ниже.

 // целые числа
$safeNumber = (int)$unsafeValue;
$safeNumber = intval($unsafeValue);

// числа с плавающей запятой
$safeNumber = (float)$unsafeValue;
$safeNumber = floatval($unsafeValue);

В большинстве случаев данные на сайт передаются через POST или GET методы. Для проверки этих переменных удобно пользоваться специальным классом JRequest. Простой пример использования JRequest:

// целые числа
$safeInt = JRequest::getInt('int');
$safeInt = JRequest::getVar('int', 0, 'DEFAULT', 'INT');
$safeInt = JRequest::getVar('int', 0, 'DEFAULT', 'INTEGER');

// числа с плавающей точкой
$safeFlt = JRequest::getFloat('float');
$safeFlt = JRequest::getVar('float', 0, 'DEFAULT', 'FLOAT');
$safeFlt = JRequest::getVar('float', 0, 'DEFAULT', 'DOUBLE');

Есть более сложный способ фильтрации данных - через класс JFilterInput. Используется он по тому же принципу, что и JRequest.

// получаем экземпляр фильтра 
$filter = JFilterInput::getInstance();
// целые числа
$safeInt = $filter->clean($unsafeValue, 'INT');
$safeInt = $filter->clean($unsafeValue, 'INTEGER');
// числа с плавающей запятой
$safeFlt = $filter->clean($unsafeValue, 'FLOAT');
$safeFlt = $filter->clean($unsafeValue, 'DOUBLE');

Какие либо данные, например числа можно взять в кавычки с помощью метода Quote базы данных:

$db->Quote((int)$unsafeValue);

В MySQL существует всего 6 различных типов, которые могут храниться как строка:

  • Строка
  • Номер
  • NULL
  • Шестнадцатеричное число
  • Булево значение
  • Bit filed

Давайте рассмотрим, как безопасно можно работать с этими типами данных MySQL.

NULL

NULL - это полное отсутствие всяких данных. Например пустая строка это не NULL. Это значение всегда должно быть записано в виде NULL либо \N.

$safeValue = ($unsafeValue == 'NULL') ? 'NULL' : 'NOT NULL';

Шестнадцатеричное число (Hexadecimal)

Для Joomla использовать шестнадцатеричные числа - это большая редкость. Поэтому в её функционале не предусмотрен такой тип данных. Но если у вас все таки возникла такая необходимость, то для проверки воспользуйтесь следующим кодом:

$matches = array();
$pattern = "~^([Xx]\'|0x)([0-9A-F]+)\'?$~";
$safeHex = $defaultSafeHexValue;
if (preg_match($pattern, $unsafeValue, $matches)) {
    $safeHex = "x'" . $matches[2] . "'";
}

Булевы значения (Boolean)

Проверка булевых типов очень проста. Если что-то пришло, то TRUE, в противном случае - FALSE:

$boolean = ($unsafeValue) ? 'TRUE' : 'FALSE' ;

Bit Field

Двоичные значения также редкость в расширениях Joomla. Опять же специальных готовых методов для этого не предусмотрено, поэтому воспользуемся следующим способом:

$matches = array();
$pattern = "~^(b\'|0b)([01]+)\'?$~";
$safeBin = $defaultSafeBinValue;
if (preg_match($pattern, $unsafeValue, $matches)) {
    $safeBin = "b'" . $matches[2] . "'";
}

Если у вас есть возможность не использовать особенные типы данных, то лучше не подвергать себя угрозе и пользоваться обычными значениями.

Смотрите также:
Оставить комментарий




* обязательно для заполнения

1 введенный почтовый адрес используется только для обратной связи при ответах в комментариях и сервиса gravatar.com
.