Sql инъекции. как вычислить и обезвредить

Содержание

Введение

В большинстве случаев уязвимости безопасности возникают только из-за недостаточной осведомленности, а не из-за халатности. Хотя мы обнаружили, что большинство разработчиков заботятся о безопасности, но иногда они не понимают, как конкретный шаблон кода может привести к уязвимости, поэтому в электронной книге мы решили поделиться наиболее распространенными проблемами безопасности, которые мы видели во время помощи разным стартапам в защите своих приложений Laravel. С каждым примером атаки мы также покажем лучшие практики по защите вашего приложения от атак. Мы надеемся, что эта информация окажется полезной для вас и вашей команды разработчиков.

CyberPanda Team

Как же происходит взлом?

Чтобы четко понимать, что именно нужно делать, программа берет SQL-запрос в кавычки. Приведу реальный пример. Допустим, мы хотим выяснить, сколько лет нашему другу, зная его имя и отправляя в переменную $_GET

Выполняем запрос:

$result = mysql_query("SELECT age FROM myfriends WHERE name=$_GET");

Например, мы хотим узнать сколько лет Насте хоть это и неприлично, но БД все нам расскажет 🙂

В программе окажется код:

mysql_query("SELECT age FROM myfriends WHERE name='Настя’");

Рассмотрим чуть детальнее вот этот кусочек. у нас есть 2 пары кавычек.

Первая пара обозначает сам запрос целиком.

"SELECT age FROM myfriends WHERE name='Настя’"

Вторая пара обозначает имя. Настя.

Так вот, а что если злоумышленник напишет не Настя, а Настя’, с кавычкой в конце? Он нарушит синтаксис функции mysql_quevery. И SQL-сервер выдаст закономерный ответ — ошибку (потому как не сможет обработать ‘ , которая не является функцией).

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near Настя'

Кстати, совсем забыл вам рассказать про оператора для комментирования. Один из них — это два тире, которые выглядят вот так: “—”.  Что же случится, если мы передадим Настя’ —  ?

Правильно. Все последующие записи закомментируются, т.е. закомментируется кавычка для закрытия функции mysql_query(). Теперь ее роль будет выполнять та кавычка, которую мы сами и написали. Верно, сейчас мы подходим к самому интересному. Таким способом мы получили доступ для свободного обращения к базе данных. Я привел в пример самую простую ошибку программиста.

В языках программирования есть разные типы данных, есть строки (String), есть числа (Integer), в зависимости от этого нужно правильно строить SQL-инъекцию. Кстати, “1” может быть как строкой, так и целым числом.

Это лишь край вершины айсберга, есть десятки способов реализации угроз типа SQL-инъекции.

Практический пример простой SQL-инъекции

Выбираем баг «SQL Injection (GET/Search)»/

От нас ожидается ввод названия фильма, введём в поиск «Iron Man»:

Далее выполним ряд тестов.

Вводим

Iron Man'

Результат

Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%'' at line 1

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

Вводим

Iron Man"

Результат

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

Исходя из полученной информации, формируем строку для вывода всех записей таблицы:

Iron Man' OR 1 #

Результат:

Пример

Рассмотрим динамический веб-сайт (в этом примере запрограммированный на PHP ), имеющий систему, позволяющую пользователям с действующим именем пользователя и паролем входить в систему. Этот сайт использует следующий SQL-запрос для идентификации пользователя:

SELECT uid FROM Users WHERE name = '(nom)' AND password = '(mot de passe hashé)';

Пользователь Dupont желает соединиться со своим паролем, хешированным в MD5 . Выполняется следующий запрос:

SELECT uid FROM Users WHERE name = 'Dupont' AND password = '45723a2af3788c4ff17f8d1114760e62';

Атаковать запрос

А теперь представьте, что PHP-скрипт, выполняющий этот запрос, не проверяет входящие данные, чтобы гарантировать их безопасность. Затем хакер может предоставить следующую информацию:

  • Пользователь:
  • Пароль: любой

Запрос становится:

SELECT uid FROM Users WHERE name = 'Dupont';--' AND password = '4e383a1918b432a9bb7702f086c56596e';

Символы отмечают начало комментария в SQL. Следовательно, запрос эквивалентен:

SELECT uid FROM Users WHERE name = 'Dupont';

Затем злоумышленник может подключиться под пользователем Dupont с любым паролем. Это успешная SQL-инъекция, потому что злоумышленнику удалось ввести символы, которые он хотел, чтобы изменить поведение запроса.

Теперь предположим, что злоумышленник хочет обмануть SQL- скрипт не над именем пользователя, а над паролем. Затем он может ввести следующий код:

  • Пользователь: Dupont
  • Пароль :

Апостроф указывает на конец зоны ввода пользователя, код »   » спрашивает скрипт, истинно ли 1, но это всегда так, а — указывает на начало комментария.

Тогда запрос становится:

SELECT uid FROM Users WHERE name = 'Dupont' AND password = '' or 1 --';

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

Экранирование специальных символов

Первое решение состоит в экранировании специальных символов, содержащихся в строках символов, введенных пользователем.

В PHP вы можете использовать функцию , которая преобразует строку в . Тогда запрос будет выглядеть следующим образом:

SELECT uid FROM Users WHERE name = 'Dupont\' -- ' AND password = '4e383a1918b432a9bb7702f086c56596e';

Апостроф в конце строки был правильно де специализирован за счет предшествующего ему символа »  \  «.

Экранирование также может быть выполнено (в зависимости от используемой СУБД ) удвоением апострофов.

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

Эта функция недостаточна для предотвращения инъекций через числовые переменные, которые не окружены апострофами или кавычками в запросах SQL. Пример с запросом:

SELECT ... FROM ... WHERE numero_badge = $numero AND code_4_chiffre = $code;

что успешно, если переменная содержит

В качестве меры предосторожности используйте функцию для проверки числовых переменных запросов. Мы также можем принудительно преобразовать переменную в число, поставив перед ней приведение типа , как если бы мы ожидали целое число (тогда строка будет преобразована в целое число, и SQL-инъекция не удастся).

Сама функция имеет некоторые недостатки в некоторых устаревших версиях PHP. Более того, он экранирует только символы «\», «NULL», «‘» и «» «. Было бы более целесообразно использовать функцию, которая точно экранирует специальные символы команды SQL (NULL, \ x1a, \ n , \ r, \, ‘, «и \ x00).

Использование подготовленного запроса

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

Многие фреймворки оснащены ORM, который, помимо прочего, отвечает за подготовку запросов.

Как искать и эксплуатировать SQLi

1. Ручной поиск. Для начала во все параметры подставляем спецсимволы: кавычки, двойные кавычки и т.д. Если на каком-то варианте вернулась ошибка, то инъекция найдена и можно продолжать. Как правило, используется оператор union select, чтобы объединить сразу 2 запроса, а как мы уже знаем, этот метод требует соответствия в количестве столбцов. С помощью order by определяем количество столбцов. После этого можно формировать запрос для получения информации о самой базе данных. Допустим у нас столбцов будет 4, то команда будет выглядеть так:

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

Отправив такой запрос, мы получим версию базы данных, имя пользователя базы данных, и порт, который использует БД (может быть полезно в случаях, когда его не удалось  определить при сканировании веб-приложения).

Указав table_name и добавив from information_schema.tables мы получим список всех таблиц базы данных, включая системные. Это стало возможным благодаря добавлению таблицы information_schema в MySQL 5.0+ и по ее наличию также можно косвенно определить версию используемой БД. Получив список таблиц ищем среди них нужную и получаем из нее информацию. Например, у нас есть таблица users, где хранятся пользовательские данные — имя пользователя, хэш пароля и прочая информация.

В результате запроса в одном поле будет выведена информация о пользователях БД (логин) и их пароли в виде хеша, используя функцию concat.

2. Автоматизация. Безусловно, навык ручного поиска и эксплуатации SQL-инъекций очень важен и порой незаменим в тестировании на проникновение, однако и время тоже является крайне ценным ресурсом. Для его экономии, особенно при поиске и эксплуатации слепых инъекций, разработаны вспомогательные  инструменты.

Один из них довольно популярен и называется SQLmap. Рассказывать про него особо нечего, так как это, думаю, первая ассоциация при слове SQL-инъекция. Но если вкратце — мощный кроссплатформенный консольный инструмент для автоматизации поиска и эксплуатации SQL-инъекций любого вида и сложности, написанный на языке Python. В основной функционал которого входит:

  • полная поддержка для таких систем управления базами данных, как:  MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM DB2, SQLite, Firebird, Sybase, SAP MaxDB и HSQLDB;

  • поддержка прямого подключения к базе данных без использования SQL инъекции, посредством введения учётных данных СУБД, IP адреса, порта и имени БД;

  • поддержка перечисления пользователей, хешей паролей, привилегий, ролей, БД, таблиц и колонок;

  • автоматическое распознавание форматов хешей паролей и предложение их взлома с использованием атаки по словарю;

  • поддержка выполнения произвольных команд на ОС сервера БД и получение их стандартного вывода при использовании MySQL, PostgreSQL или Microsoft SQL Server и многое другое.

Основные ключи, которые используются при работе с инструментом:

  • —dbs — поиск и вывод списка баз данных;

  • -D,T,C — указание конкретной базы данных, таблицы и колонок в таблице для дампа информации из них;

  • —level, —risk — параметры для более углубленного тестирования (параметры генерируют больше трафика и могут помочь системам защиты выявить атаку);

  • —random-agent — использование произвольного User-Agent.

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

Экранирование значений

Что делать, если в SQL запрос требуется подставить строковое значение? Например, на сайте есть возможность поиска города по его названию. Форма поиска передаст поисковый запрос в GET-параметр, а мы используем его в SQL-запросе:

Но если в параметре будет символ кавычки, то смысл запроса можно кардинально изменить. Передав в search_text значение , мы выполним запрос, что выведет список всех городов:

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

Экранирование добавляет в строке перед кавычками (и другими спецсимволами) знак обратного слэша .
Такая обработка лишает кавычки их статуса — они больше не определяют конец значения и не могут повлиять на логику SQL-выражения.

За экранирование значений отвечает функция .
Этот код обработает значение из параметра, сделав его безопасным для использования в запросе:

Методы предотвращения и защиты от MySQL-инъекций

  • Использование параметризованных запросов
  • Использование хранимых процедур
  • Применение регулярных выражений
  • Использование функций блокировки
  • Отключение сообщений об ошибках
  • Создание менее привилегированного пользователя
  • Ограничения максимального значение

1. Использование параметризованных запросов

<?php

$db_connection = new mysqli("localhost", "user", "pass", "db");
$statement = $db_connection->prepare("SELECT * FROM customers WHERE id = ?");
$statement->bind_param("i", $id);
$statement->execute();

?>

2. Использование хранимых процедур

<?php

$sqlStatement = "
	CREATE PROCEDURE HUGEORDER
	(
		id INT ,
		quantity INT,
		price DECIMAL(6,2)
	)
	BEGIN
		DECLARE discount_percent DECIMAL(6,2);
		DECLARE discounted_price DECIMAL(6,2);
		SET discount_percent  =  10;
		SET discounted_price = price – discount_percent/100*price;
		IF quantity > 500 THEN
			SET discounted_price = discounted_price - 0.25 * quantity;
		END  IF;
		UPDATE fashion_products
		SET product_price = discounted_price WHERE product_id = id;
		Select * from fashion_products;
	END;
";

?>

3. Применение регулярных выражений

SQL-инъекций

<?php

if(!preg_match("/^+@(+\.)+{2,}$/i", $email))
{
        echo 'INVALID Email Address!';
	return;
}

?>

is_array(), is_bool(), is_double(), is_float(), is_int(), is_integer()

4. Использование функции блокировки

mysql_real_escape_string()

<?php

$username = mysql_real_escape_string($username, $ dbLink);

?>

mysql_real_escape_string()

5. Отключение сообщений об ошибках

mysql_error()mysql_error()

<?php

// Отключить вывод ошибок
error_reporting(0);

?>
<?php

if(!mysql_query($statement))
{
	echo 'Извините, но сервер не доступен!';
}

?>

6. Создайте менее привилегированного пользователя БД

<?php

$visitorDbLink = mysql_connect('host', 'general_user', 'general_user_pass');
$adminDbLink = mysql_connect('host', 'admin_user', 'admin_pass');

?>

7. Установите ограничения на максимальное значение

<input name="username" type="text" id="username" maxlength="10" />
<?php

$name = substr($_POST,0,10);

?>

substr()P.S. В статье Слепая SQL-инъекция я рассмотрел новые способы защиты от разновидности SQL-уязвимостей.

Тэги: sql-инъекция • php

32 333 просмотра

SQL-инъекции

Laravel предоставляет надежный конструктор запросов (Query Builder) и Eloquent ORM. И, благодаря им, большинство запросов по-умолчанию защищены в приложениях, поэтому, например, запрос типа

будет автоматически защищен, так как Laravel переведет код в подготовленный оператор и выполнит.

Но разработчики обычно делают ошибки, полагая, что Laravel защищает от всех SQL-инъекций, хотя есть некоторые векторы атак, которые Laravel не может защитить.

Вот наиболее распространенные причины SQL-инъекций, которые мы видели в современных приложениях Laravel во время наших проверок безопасности.

1. SQL-инъекция через имя столбца

Первая распространенная ошибка, которую мы видим, заключается в том, что многие люди думают будто Laravel будет избегать любого параметра, переданного в Query Builder или Eloquent. Но, на самом деле, это не так безопасно передавать имена столбцов, управляемых пользователем, в конструктор запросов.

Вот предупреждение от :

Таким образом, следующий код будет уязвим для SQL-инъекции:

и если кто-то делает запрос со следующим значением параметра

под капотом будет выполнен следующий запрос и мы получим успешную SQL-инъекцию:

Важно отметить, что показанный вектор атаки исправлен в последней версии Laravel*, но, тем не менее, Laravel предупреждает разработчиков даже в свежей документации, чтобы они не передавали имена столбцов в Query Builder от пользователей без их добавления в белый список. В общем, даже если нет возможности превратить настраиваемый столбец во внедренную SQL-инъекцию, мы по-прежнему не рекомендуем разрешать сортировку данных по любому столбцу, заданному пользователем, так как это может создать угрозу безопасности

В общем, даже если нет возможности превратить настраиваемый столбец во внедренную SQL-инъекцию, мы по-прежнему не рекомендуем разрешать сортировку данных по любому столбцу, заданному пользователем, так как это может создать угрозу безопасности.

Рассмотрим пример, когда таблица «users» может иметь какой-то секретный столбец «secretAnswer», умный злоумышленник может вывести значение без необходимости SQL-инъекции.

2. SQL-инъекция с помощью правил валидации

Давайте посмотрим на следующий упрощенный код проверки

Поскольку Laravel использует здесь для запроса этой и значение не экранируется, это позволит злоумышленнику выполнить SQL-инъекции. Мы рассмотрим эту атаку более подробно в «Инъекция правил валидатора» > «SQL-инъекция».

3. SQL-инъекция через необработанные запросы

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

Экранирование кавычек

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

Возьмём такой пример:

С этим запросом всё в порядке, он выполнится как мы и ожидаем:

Но что если в переменной $name будет одинарная кавычка?

Тогда SQL-запрос станет таким:

Попытка выполнить этот запрос приведёт к ошибке синтаксиса. Чтобы её не было, вторую кавычку нужно экранировать, т.е. добавить к ней обратный слеш.

Способы экранирования и их надёжность разберём чуть ниже, а сейчас для простоты возьмём addslashes():

Что будет в итоге:

Готово, запрос выполнится даже при наличии кавычек.

Экранировать можно не только кавычки. Разные функции умеют экранировать разные символы, об этом мы подробно поговорим чуть позже.

А теперь важный момент. Некоторые разработчики считают, экранирования достаточно для полной защиты от SQL-инъекций.

Хорошо, ещё раз посмотрим на самый первый пример с SQL-инъекцией:

В этом запросе нет никаких кавычек. Но уязвимость есть. Отсюда делаем вывод, что экранирование не гарантирует защиту от SQL-инъекций.

объяснение

Оператор SQL, который вы передаете для , анализируется и компилируется сервером базы данных. Указывая параметры (или Или именованный параметр, такой как в приведенном выше примере), вы указываете ядру базы данных, куда вы хотите фильтровать. Затем при вызове подготовленный оператор объединяется с указанными вами значениями параметров.

Здесь важно то, что значения параметров объединяются с скомпилированным оператором, а не строкой SQL. SQL-инъекция работает, обманывая скрипт, добавляя в него вредоносные строки, когда он создает SQL для отправки в базу данных

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

Любые параметры, которые вы отправляете при использовании подготовленного оператора, будут просто обрабатываться как строки (хотя ядро базы данных может выполнить некоторую оптимизацию, поэтому, конечно, параметры могут также оказаться числами). В приведенном выше примере, если переменная содержит результатом будет просто поиск строки , и вы не получите пустую таблицу.

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

Да, и так как вы спросили о том, как сделать это для вставки, вот пример (с использованием PDO):

Пример SQL инъекция для веб формы

Предположим, аутентификация в Web- приложение осуществляется с помощью Web- формы, обрабатываемой следующим кодом:

SQLQuery = "SELECT Username FROM Users WHERE
Username = '" & strUsername & "' AND Password = '"
& strPassword & "'" strAuthCheck =
GetQueryResult(SQLQuery)

В этом случае разработчики непосредственно использует переданные пользователями значения strUsername и strPassword для создания SQL- запроса. Предположим, злоумышленник передаст следующие значения параметров:

Login: ' OR ''='
Password: ' OR ''='

В результате серверу будет передан следующий SQL-запрос:

SELECT Username FROM Users WHERE Username = '' OR ''='' AND Password = '' OR ''=''

Вместо сравнения имени пользователя и пароля с записями в таблице Users, данный запрос сравнивает пустую строку с пустой строкой. Естественно, результат подобного запроса всегда будет равен True, и злоумышленник войдет в систему от имени первого пользователя в таблице.

Обычно выделяют два метода эксплуатации внедрения операторов SQL: обычная атака, и атака вслепую (Blind SQL Injection). В первом случае злоумышленник подбирает параметры запроса, используя информацию об ошибках, генерируемую Web- приложением.

Пример: Добавляя оператор union к запросу злоумышленник проверяет доступность базы данных: http://example/article.asp?ID=2+union+all+select+name+from+sysobjects

Сервер генерирует сообщение, аналогичное следующему:

Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
All
queries in an SQL statement containing a UNION
operator must have an equal number of expressions
in their target lists.

Из этого следует, что оператор union был передан серверу, и теперь злоумышленнику необходимо подобрать используемое в исходном выражении select количество параметров. Внедрение SQL кода вслепую. В этом случае стандартные сообщения об ошибках модифицированы, и сервер возвращает понятную для пользователя информацию о неправильном вводе. Осуществление SQL Injection может быть осуществлено и в этой ситуации, однако обнаружение уязвимости затруднено.
Наиболее распространенный метод проверки наличия проблемы – добавление выражений, возвращающих истинное и ложное значение.
Выполнение подобного запроса к серверу: http://example/article.asp?ID=2+and+1=1 должно вернуть ту же страницу, что и запрос: http://example/article.asp?ID=2 поскольку выражение ‘and 1=1’ всегда истинно.
Если в запрос добавляется выражение, возвращающее значение «ложь»: http://example/article.asp?ID=2+and+1=0 пользователю будет возвращено сообщение об ошибках или страница не будет сгенерирована. В случае если факт наличие уязвимости подтвержден, эксплуатация ничем не отличается от обычного варианта.

Ссылки SQL Injection

  • WASC: SQL Injection

  • SQL Injection Walkthrough

  • «CWE-89: Failure to Preserve SQL Query Structure (aka ‘SQL Injection’)»

  • CAPEC: SQL Injection

  • OWASP: SQL Injection

  • Управление Microsoft SQL Server используя SQL инъекции

  • Внедрение SQL кода с завязанными глазами

  • SQL инъекция и ORACLE

Referrer-Policy

Браузеры автоматически добавляют в заголовки запросов при переходе на какой-то сайт ссылку на сайт с которого был совершен переход. Это очень удобно для аналитики. Например, не составит большого труда написать какой-то код, который составит для вас статистику со списком сайтов с которых посетители заходят на ваш сайт. Однако, если в стоке адреса на вашем сайте имеются запросы с какой-то конфиденциальной информацией, то очень желательным было бы скрыть эту информацию от других сайтов. Например: http://www.somegoodsite.com/Edit?id=34543276654

Для того чтобы скрыть вашу ссылку при переходе на чужой сайт можно установить заголовок со значением «Referrer-Policy: no-referrer»

Второй способ: защита от sql инъекций PHP и PDO

PDO — это встроенный класс PHP, который обеспечивает современную связь с БД, объектно-ориентированный подход и встроенную защиту от инъекций.

В PDO есть встроенная функция prepare, которая подготавливает запрос к выполнению с учетом предполагаемых параметров, и функция execute, в которую можно передавать параметры для выполнения запроса.

Рассмотрим на примере:

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute(array('column' => $unsafeValue));

Думаю, из кода и так всё понятно, но поясню.
Сначала мы создаём запрос к БД (пока это только объект на PHP) — $preparedStatement

При создании (с помощью prepare) мы указали, что в запросе будет участвовать один параметр :column (параметров может быть сколько угодно, но важно, чтобы декларации этих параметров в запросе начинались с двоеточия.
Затем мы выполняем запрос, передавая массив параметров для подстановки в запрос с функцией execute. При этом все переменные, передаваемые в запрос с функцией execute автоматически защищаются от SQL инъекций

Вообще говоря, если версия PHP позволяет, использование PDO не только безопаснее, но и удобнее с точки зрения кода, и быстрее с точки зрения выполнения запросов (у них есть встроенный механизм работы с транзакциями, запросами и многим другим). Но об использовании PDO в следующих выпусках.

Спасибо за внимание, надеюсь приведенные примеры помогут вам в защита от sql инъекций ваших сайтов. Уверен, что этой информацией владеют в школе HTML и CSS, и успешно раскажут вам защиту от SQL инъекций в своих проектах по созданию сайтов

Уверен, что этой информацией владеют в школе HTML и CSS, и успешно раскажут вам защиту от SQL инъекций в своих проектах по созданию сайтов

1 640

Open redirect attacks

Будьте аккуратнее с редиректами. Следующий код очень опасен:

Атакующий может добавить ссылку на свой сайт. А пользователь же, увидев, что URL начинается с хорошего сайта, может не рассматривать адрес полностью (особенно если он длинный) а кликнуть ссылку, таким образом перейдя на вредный сайт с вашего. Эта уязвимость может использоваться в частности для фишинга. Пример фишинговой ссылки:http://www.goodwebsite.com/Redirect?url=http://www.goodweebsite.com

Этот вид атак касается и MVC. В следующем примере происходит проверка на то является ли ссылка локальной:

Для защиты от этого типа атак можно использовать и вспомогательный метод LocalRedirect

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

SQL Учебник

SQL ГлавнаяSQL ВведениеSQL СинтаксисSQL SELECTSQL SELECT DISTINCTSQL WHERESQL AND, OR, NOTSQL ORDER BYSQL INSERT INTOSQL Значение NullSQL Инструкция UPDATESQL Инструкция DELETESQL SELECT TOPSQL MIN() и MAX()SQL COUNT(), AVG() и …SQL Оператор LIKESQL ПодстановочныйSQL Оператор INSQL Оператор BETWEENSQL ПсевдонимыSQL JOINSQL JOIN ВнутриSQL JOIN СлеваSQL JOIN СправаSQL JOIN ПолноеSQL JOIN СамSQL Оператор UNIONSQL GROUP BYSQL HAVINGSQL Оператор ExistsSQL Операторы Any, AllSQL SELECT INTOSQL INSERT INTO SELECTSQL Инструкция CASESQL Функции NULLSQL ХранимаяSQL Комментарии

7. Операции с файлами после обнаружения SQL-инъекций

Кроме операций с базами данных — их чтение и модификация, в случае обнаружения SQL-инъекций возможно выполнение следующих файловых операций:

  • чтение файлов на сервере
  • выгрузка новых файлов на сервер
  • выгрузка шеллов на сервер

И всё это реализовано в jSQL Injection!

Есть ограничения — у SQL-сервера должны быть файловые привилегии. У разумных системных администраторов они отключены и доступа к файловой системе получить не удастся.

Наличие файловых привилегий достаточно просто проверить. Перейдите в одну из вкладок (чтение файлов, создание шелла, закачка нового файла) и попытайтесь выполнить одну из указанных операций.

Ещё очень важное замечание — нам нужно знать точный абсолютный путь до файла с которым мы будем работать — иначе ничего не получится.

Посмотрите на следующий скриншот:

На любую попытку операции с файлом нам отвечают: No FILE privilege (нет файловых привелегий). И ничего здесь поделать нельзя.

Если вместо этого у вас другая ошибка:

Problem writing into 

Это означает, что вы неправильно указали абсолютный путь, в который нужно записывать файл.

Для того, чтобы предположить абсолютный путь, нужно, как минимум, знать операционную систему на которой работает сервер. Для этого переключитесь к вкладке Network.

Такая запись (строка Win64) даёт основание нам предположить, что мы имеем дело с ОС Windows:

Keep-Alive: timeout=5, max=99
Server: Apache/2.4.17 (Win64) PHP/7.0.0RC6
Connection: Keep-Alive
Method: HTTP/1.1 200 OK
Content-Length: 353
Date: Fri, 11 Dec 2015 11:48:31 GMT
X-Powered-By: PHP/7.0.0RC6
Content-Type: text/html; charset=utf-8

Здесь у нас какой-то из Unix (*BSD, Linux):

Transfer-Encoding: chunked
Date: Fri, 11 Dec 2015 11:57:02 GMT
Method: HTTP/1.1 200 OK
Keep-Alive: timeout=3, max=100
Connection: keep-alive
Content-Type: text/html
X-Powered-By: PHP/5.3.29
Server: Apache/2.2.31 (Unix)

А здесь у нас CentOS:

Method: HTTP/1.1 200 OK
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Set-Cookie: PHPSESSID=9p60gtunrv7g41iurr814h9rd0; path=/
Connection: keep-alive
X-Cache-Lookup: MISS from t1.hoster.ru:6666
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.4.37
X-Cache: MISS from t1.hoster.ru
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Date: Fri, 11 Dec 2015 12:08:54 GMT
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8

В Windows типичной папкой для сайтов является C:\Server\data\htdocs\. Но, на самом деле, если кто-то «додумался» делать сервер на Windows, то, весьма вероятно, этот человек ничего не слышал о привилегиях. Поэтому начинать попытки стоит прямо с каталога C:/Windows/:

Как видим, всё прошло прекрасно с первого раза.

Но вот сами шеллы jSQL Injection у меня вызывают сомнения. Если есть файловые привилегии, то вы вполне можете закачать что-нибудь с веб-интерфейсом.

Сложности с оператором LIKE в PDO

У оператора LIKE есть два собственных спецсимвола «_» и «%». Чтобы искать буквальное совпадение с этими символами, их необходимо прослэшить функцией addCslashes().

$data = addCslashes($data, '\%_');

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

$name = "%$name%";
$STH = $DB->prepare("SELECT*FROM table_name WHERE name LIKE ?");
$STH->execute(array($name));
$data = $STH->fetchAll();

Использование оператора IN в PDO

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

# набор знаков вопроса через запятую по числу элементов в IN()

$in = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT*FROM table_name WHERE column IN($in)";          # массив данных для подстановки.
$arr = array(1,2,3);

Собственно говоря, это основные знания для полноценной работы с PDO. Назовем данную статью справочником понятий и рецептов работы с PDO, который я собирал и продолжаю собирать, по мере поступления новых проблем, со всего интернета в одном месте.