Это работает, чтобы остановить инъекции sql - PullRequest
3 голосов
/ 12 ноября 2011

Я использовал блок кода ниже, чтобы якобы остановить инъекции SQL. Это то, что кто-то показал мне, когда я впервые запустил php (что было не так давно)

Я размещаю его на каждой странице, как показано на открытой странице. Мне интересно, если это эффективно? Я не знаю, как проверить на инъекции sql

<?php

//Start the session

session_start();


//=======================open connection

include ('lib/dbconfig.php');

//===============This stops SQL Injection in POST vars

  foreach ($_POST as $key => $value) {
    $_POST[$key] = mysql_real_escape_string($value);
  }

  foreach ($_GET as $key => $value) {
    $_GET[$key] = mysql_real_escape_string($value);
  }

Мои типичные запросы на вставку и обновление выглядят так

$insert = ("'$email','$pw','$company', '$co_description', '$categroy', '$url', '$street', '$suite', '$city', '$state', '$zip', '$phone', '$date', '$actkey'");

mysql_query("INSERT INTO provider (email, pw, company, co_description, category, url, street, suite, city, state, zip, phone, regdate, actkey) VALUES ($insert)") or die ('error ' . mysql_error());

mysql_query("UPDATE coupon SET head='$_POST[head]', fineprint='$_POST[fineprint]', exdate='$exdate', creationdate=NOW() WHERE id='$cid'") or die ('error ' . mysql_error());

Ответы [ 5 ]

4 голосов
/ 12 ноября 2011

Это несколько эффективно, но неоптимально - не все данные, которые вы получаете в _GET и _POST, попадут в базу данных.Иногда вам может понадобиться отобразить его на странице, и в этом случае mysql_real_escape_string может только навредить (вместо этого вы захотите htmlentities).

Мое эмпирическое правило - только избегать чего-либо непосредственно перед тем, как поместить его вконтекст, в котором его необходимо экранировать.

В этом контексте вам лучше всего использовать параметризованные запросы - тогда экранирование будет выполнено автоматически.

3 голосов
/ 12 ноября 2011

Этого недостаточно.1. Вам не хватает файлов cookie, переменная $ _COOKIE.2. Если вы используете $ _REQUEST, у вас проблемы.3. Вы не показывали свои запросы, вы должны заключать каждую переменную в одинарные кавычки, когда вы помещаете их в запрос (особенно, когда предполагается, что данные являются целыми числами, и вы можете подумать, что в этом случае кавычка не нужна,но это было бы большой ошибкой).4. Данные, используемые в вашем запросе, могут поступать из другого источника.

Лучший способ - использовать привязку данных и автоматически экранировать данные драйвером, это доступно в расширении PDO.

Пример кода:

$PDO = new PDO('mysql:dbname=testdb;host=127.0.0.1' $user, $password);
$stmt = $PDO->prepare("SELECT * FROM test WHERE id=? AND cat=?");
$stmt->execute(array($_GET["id"], $_GET["cat"]));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

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

$stmt = $PDO->prepare("SELECT * FROM test WHERE id = :id AND cat = :cat");
$stmt->execute(array(":id" => $_GET["id"], ":cat" => $_GET["cat"]));

Если вы хотите изучить PDO, вам могут пригодиться следующие вспомогательные функции, которые я использую:

http://www.gosu.pl/var/PDO.txt

PDO_Connect(dsn, user, passwd) - connects and sets error handling.
PDO_Execute(query [, params]) - only execute query, do not fetch any data.
PDO_InsertId() - last insert id.

PDO_FetchOne(query [, params]) - fetch 1 value, $count = PDO_FetchOne("SELECT COUNT(*) ..");
PDO_FetchRow(query [, params]) - fetch 1 row.
PDO_FetchAll(query [, params]) - fetch all rows.
PDO_FetchAssoc(query [, params]) - returns an associative array, when you need 1 or 2 cols

1) $names = PDO_FetchAssoc("SELECT name FROM table");
the returned array is: array(name, name, ...)

2) $assoc = PDO_FetchAssoc("SELECT id, name FROM table")
the returned array is: array(id=> name, id=>name, ...)

3) $assoc = PDO_FetchAssoc("SELECT id, name, other FROM table");
the returned array is: array(id=> array(id=>'',name=>'',other=>''), id=>array(..), ..)

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

2 голосов
/ 12 ноября 2011

Вид.

Функция mysql_real_escape_string берет указанную переменную и экранирует ее для запросов SQL.Таким образом, вы можете безопасно добавлять строку в запрос, например

$safe =  mysql_real_escape_string($unsafe_string);
$query = 'SELECT * FROM MyTable WHERE Name LIKE "' . $safe . '" LIMIT 1';

. Он НЕ защищает вас от того, что кто-то вставит вредоносный код в этот запрос для последующего отображения (например, XSS или аналогичная атака).Поэтому, если кто-то установит переменную равной

// $unsafe_string = '<script src="http://dangerous.org/script.js"></script>'
$safe =  mysql_real_escape_string($unsafe_string);
$query = 'UPDATE MyTable SET Name = "' . $safe . '"';

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

1 голос
/ 15 ноября 2011

Это совершенно НЕПРАВИЛЬНЫЙ подход.

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

0 голосов
/ 12 ноября 2011

это не для того, чтобы предотвратить SQL-инъекцию, настоящий метод escape только добавляет \ к опасному

символов, таких как "или", поэтому строка с "hi" do'like "станет" hi \ "do \ 'like \", поэтому это

менее опасно

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

переменная на странице, она только уничтожит ее и сделает ее менее читаемой

...