Решение для инъекций MySQL - PullRequest
0 голосов
/ 07 мая 2010

Меня так долго беспокоили инъекции MySQL, и я думал о том, как полностью решить эту проблему. Я придумал что-то ниже , надеюсь, что многие найдут это полезным.

Единственный откат, который я могу вспомнить, это частичный поиск: Jo => возвращает «John», используя оператор %%.

Вот решение php:

<?php
function safeQ(){
   $search= array('delete','select');//and every keyword...
   $replace= array(base64_encode('delete'),base64_encode('select'));
   foreach($_REQUEST as $k=>$v){
      str_replace($search, $replace, $v);
   }
}
safeQ();

function html($str){
   $search= array(base64_encode('delete'),base64_encode('select'));
   $replace= array('delete','select');//and every keyword...
   str_replace($search, $replace, $str);
}

//example 1
...
...
$result = mysql_fetch_array($query);
echo html($result[0]['field_name']);

//example 2
$select = 'SELECT * FROM $_GET['query'] '; 

//example 3
$insert = 'INSERT INTO .... value( $_GET['query'] )'; 


?>

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

Так что мой вопрос: если кто-то может найти какие-либо недостатки в этом, то, пожалуйста, не стесняйтесь комментировать здесь.

ПОЖАЛУЙСТА, ДАЙТЕ ОТВЕТ, только если вы считаете, что это очень полезное решение, и никаких серьезных недостатков не найдено ИЛИ вы считаете, что это плохая идея все вместе ...

Ответы [ 4 ]

11 голосов
/ 07 мая 2010

Это уже правильно реализовано в PHP:

Тем не менее, вы должны начать с чтения PHP-записи о внедрении SQL .


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

  1. не работает
  2. Просто чтобы прояснить, это не работает и оставит вас широко открытыми для SQL-инъекций.
  3. Он также предотвращает ввод любых данных, конфликтующих с ключевым словом MySQL.

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

6 голосов
/ 07 мая 2010

Изобретая колесо и изобретая его по неправильному пути (TM).

  • Прежде всего, есть параметризованные запросы (для PHP доступно расширение MySQLi ); если это не вариант, есть mysql_real_escape_string . Это главная проблема - проверьте уже имеющиеся опции, прежде чем принимать решение о их реализации самостоятельно.
  • Во-вторых, вы пытаетесь вызывать PHP-функции в SQL, то, что вы хотели, вероятно, было что-то вроде 'SELECT * FROM ' . safeQ($_GET['query'])
  • В-третьих, вы нарушили всю индексацию и поиск по данным, содержащим ваши «злые слова», скажите привет проблемам с производительностью и сумасшедшим решениям.

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

$v="1; DROP tbl;\";DROP tbl" // oh look, an SQL injection attempt!
$s = 'SELECT * FROM tbl WHERE ID='.$v; // SQL injection, no doubt

// if ID is an integer field, make it an integer. Simple, secure, and fast.
$s = 'SELECT * FROM tbl WHERE ID='.(int)$v; 
// $s == 'SELECT * FROM tbl WHERE ID=1' // see PHP manual for explanation of type casting

// if ID is a string field, escape it. Simple, secure, and still plenty fast.
$s = 'SELECT * FROM tbl WHERE ID="'.mysql_real_escape_string($v) . '"';
// $s == 'SELECT * FROM tbl WHERE ID="1; DROP tbl;\";DROP tbl"'; 
// See? No injection, as the quote is *escaped*
2 голосов
/ 07 мая 2010

Это плохая идея.

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

Это называется параметрами.

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

Любое другое решение, которое пытается «исправить» проблему, просматривая SQL или его части и пытаясь определить, является ли оно правильным, находится на уровне ниже нормы, и большинствоиз них есть другие ошибки и проблемы, о которых вы не можете видеть, о которых не знаете, и не хотите их иметь.

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

В PHP, говоря с MySQL, существует несколько способов, но с помощью библиотеки mysqli:

$stmt = $db->prepare('SELECT * FROM products WHERE id = ?');
$stmt->bind_param('i', $id);
$stmt->execute();
.. bind for results
$stmt->fetch();

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

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

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

1 голос
/ 07 мая 2010

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

  1. Существует специальная атака, называемая «SQL-инъекция».
  2. Чтобы предотвратить это, входным данным нужно угрожать каким-то особым образом.

Они оба не правы.

Не существует такой вещи, как «SQL-инъекция» , когда вы следуете синтаксису SQL.

Пойди разберись.

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

Любые строковые данные, помещаемые в SQL-запрос, должны обрабатываться двумя правилами:
1. все специальные символы в строке должны быть экранированы.
2. строка должна быть заключена в кавычки.

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

Хотя все еще есть проблемы с частями запроса, не относящимися к данным. Это действительно самая опасная часть. И единственную проблему имеют право называться «SQL-инъекцией».
Чтобы избежать этого, все динамические части запроса, не относящиеся к данным, должны быть жестко закодированы в вашем скрипте. Это единственный возможный способ.

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