Защита от SQL-инъекций - PullRequest
       5

Защита от SQL-инъекций

6 голосов
/ 08 сентября 2011

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

В настоящее время у меня есть учетная запись администратора, которая, очевидно, дает мне полную команду над базой данных (alter, drop и т. Д.). У меня есть учетная запись, которую использует PHP, которая имеет доступ только к SELECT, UPDATE, DELETE, INSERT. А как насчет настройки пользователя для каждого из этих действий, а затем просто ссылки на идентификатор соединения в операторе mysql_query - теперь, очевидно, это значительно увеличит нагрузку на сервер, по сути, придется делать 4 соединения на страницу, но если это безопасность важно, мне кажется, что это будет допустимая опция, ограничивая команды функцией EXACT, которую вы хотите выполнить в этом случае. Есть мысли по поводу жизнеспособности этой опции?

ОБНОВЛЕНИЕ: Как я не упомянул ранее, это НЕ будет единственным препятствием для предотвращения внедрения SQL, mysql_real_escape_string (), подготовленных операторов и т. Д. Но я просто подумал, что если каким-то образом, ВСЕ из них не удастся Разве это не ограничивает ущерб, который они могут нанести? (например, в регистрационной форме они не смогут ВЫБРАТЬ хэши или УДАЛИТЬ записи).

Ответы [ 4 ]

9 голосов
/ 08 сентября 2011

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

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

$sql = "SELECT COUNT(*) AS count
          FROM users 
         WHERE user_id='{$_POST['user']}' AND pass='{$_POST['password'}'";

// check if returns a count of 1, if yes, log in

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

SELECT COUNT(*) AS count
  FROM users 
 WHERE user_id = 'username' AND pass='********'

, который должен возвращать 1 как число, если имя пользователя и пароль совпадают,Теперь злоумышленник пытается войти в систему как администратор.Поскольку вы не очистили свои данные, они отправляют $_POST['user'] как: admin'; --.Весь запрос становится следующим:

SELECT COUNT(*) AS count
  FROM users 
 WHERE user_id = 'admin'; -- AND pass='********'

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


Короче говоря, учетная запись для всего приложения с ограниченными привилегиями (например, нет DROPALTER и т. Д.) Это хорошо.Никогда не предоставляйте никому или любому приложению больше привилегий, чем им нужно.Но чтобы предотвратить внедрение SQL, используйте подготовленные операторы .

2 голосов
/ 08 сентября 2011

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

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

mysql_query('DELETE FROM posts WHERE user_id = '.$user_id
           .' AND post_id = '.$_GET['post_id']);

Злоумышленник может с легкостью удалить все ваши сообщения, установив для post_id значение 1 OR 1=1:

http://www.example.com/delete_post.php?post_id=1+OR+1%3D1

ПолучитьДля правильной защиты вы всегда должны избегать использования строк в запросе:

$_GET['post_id'] = mysql_real_escape_string($_GET['post_id']);

Или лучше использовать подготовленные операторы.

1 голос
/ 23 сентября 2011

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

Поэтому не изобретайте новые магические щиты и способы защиты от магической опасности инъекции! Вместо этого, попытайтесь понять, как работает экранирование ввода.

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

');DROP TABLE table;--

после экранирования:

\');DROP TABLE table;--

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

insert into posts set title = '\');DROP TABLE table;--'

В этом нет ничего магического, как щит безопасности или что-то в этом роде, просто нужно убедиться, что результирующий запрос имеет правильный синтаксис! (конечно, если это не так, он может бытьэксплуатируется)

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

');DROP TABLE table;--

, которое точно соответствует значению, введенному пользователем.И это именно то, что вы хотели иметь в базе данных !!

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

Но, в вашем примере, очень важно упомянуть директиву magic_quotes_gpc!

Эта функция не используетсявсе пользовательский ввод автоматически (gpc - _GET, _POST и _COOKIE). Это злая функция, созданная для людей, которые не знают о внедрении SQL.Это зло по двум причинам. Первая причина в том, что тогда вы должны различать регистр вашего первого и второго запроса - в первом вы не убегаете, а во втором вы делаете.Большинство людей делают либо отключение «функции» (я предпочитаю это решение), либо сначала отключение пользовательского ввода, а затем повторение при необходимости.Код unescape может выглядеть следующим образом:

function stripslashes_deep($value)
{
        return is_array($value) ?
               array_map('stripslashes_deep', $value) :
               stripslashes($value);
}

if (get_magic_quotes_gpc()) {
        $_POST = stripslashes_deep($_POST);
        $_GET = stripslashes_deep($_GET);
        $_COOKIE = stripslashes_deep($_COOKIE);
}

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

  1. строковое значение для запроса mysql
  2. like выражениедля запроса MySQL
  3. HTML-код
  4. JSON
  5. MySQL регулярное выражение
  6. PHP регулярное выражение

Для каждого случая вынужно различное цитирование, потому что каждое использование присутствует в различном синтаксическом контексте.Это также подразумевает, что цитирование должно производиться не при вводе в PHP, а при конкретном выводе !Именно поэтому такие функции, как magic_quotes_gpc, не работают ( никогда не забывайте обращаться с ним, или, что еще лучше, убедитесь, что он выключен !!! ).

Итак, какими методамииспользовать для цитирования в этих конкретных случаях?(Не стесняйтесь поправлять меня, могут быть более современные методы, но они работают для меня)

  1. mysql_real_escape_string($str)
  2. mysql_real_escape_string(addcslashes($str, "%_"))
  3. htmlspecialchars($str)
  4. json_encode() - только для utf8!Я использую свою функцию для iso-8859-2
  5. mysql_real_escape_string(addcslashes($str, '^.[]$()|*+?{}')) - вы не можете использовать preg_quote в этом случае, потому что обратный слэш будет экранирован два раза!
  6. preg_quote()
1 голос
/ 08 сентября 2011

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

Подробнее о SQL-инъекциях: SQL-инъекции и PDO

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