Предотвращение SQL-инъекций для запросов только INSERT.Это большое дело? - PullRequest
0 голосов
/ 07 февраля 2012

Я впервые создаю форму PHP, которая будет выполнять запрос MySQL, используя INSERT INTO для хранения данных в рабочей БД.Будет ли это проходить как «безопасный» или это чрезмерное убийство?

$orderText = $mysqli->real_escape_string(stripslashes(htmlentities((!isset($_POST["order_text"])?"undefined":$_POST["order_text"]))));
$stmt = $mysqli->prepare("INSERT INTO testtable (order_text) VALUES (?)");
$stmt->bind_param('s',$orderText);
$stmt->execute();

Я не уверен, как отсутствие SELECT * влияет на величину риска, которому я себя открываю, нопохоже, что сценарий, который использует только INSERT, безопаснее.Правда?

Ответы [ 4 ]

2 голосов
/ 07 февраля 2012

В вашем вопросе много ложных предположений.

  1. Это, безусловно, излишество.
    Давайте рассмотрим ваш чрезвычайно трудный для чтения зиллион-nested-operator оператор:

    • хранение слова 'undefined' не имеет смысла.В базе данных есть специальная отметка для неопределенных полей - значение NULL.Либо просто пустой строки будет достаточно.
    • Безусловные полосные черты ничего не добавляют к безопасности, но могут испортить данные.
    • htmlentities не имеет ничего общего с безопасностью SQL, может помочь с безопасностью сайта в других аспектахи может также испортить данные.
    • экранирование ничего не добавляет к безопасности и не испортит данные.
  2. Вы берете проблему не с того конца.
    Ваша основная задача - правильно отформатировать ваш запрос.Не для защиты от мнимых «злоумышленников», а для предотвращения сбоя с помощью самых честных данных.Хотя правильно отформатированный запрос будет неуязвим для различных атак просто как побочный эффект.
    Скажем, real_escape_string не имеет ничего общего с безопасностью.Он используется только для форматирования строк.В вашем запросе нет строк (данных, заключенных в кавычки), поэтому эта функция совершенно бесполезна (и даже вредна).

  3. Фактически, инъекция через INSERT не менее катастрофична, чем через SELECT.

Наконец, правильный код будет

$stmt = $mysqli->prepare("INSERT INTO testtable (order_text) VALUES (?)"); 
$stmt->bind_param('s',$_POST["order_text"]); 
$stmt->execute(); 

, и при печати текста заказа обратно на сайт используйте htmlspecialchars()

, этовсе.

2 голосов
/ 07 февраля 2012

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

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

1 голос
/ 07 февраля 2012

Я согласен с Чарльзом, связывая параметр, вы уже правильно экранируете переменную, исключая вероятность атаки SQL-инъекцией, и сложность строки 1 является чрезмерной. Это станет очевидным, когда вы перейдете к PDO , потому что нет конкретного вызова $ dbo-> escape (), поскольку экранирование уже завершено с вызовами prepare () / bind () .

1 голос
/ 07 февраля 2012

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

...