Как предотвратить SQL инъекции кода в мой код PHP?
я Разработал простую страницу на PHP для внутреннего использования в компании, что работа, и только очень немногие люди используют его. С помощью этой страницы можно сделать некоторые запросы, вставки, изменения и удаления данных из таблицы в базе данных MySQL, однако я считаю, что мой код в PHP не защищен от SQL инъекции кода, например:
//----CONSULTA SQL----//
$busca = mysql_query ('insert into Produtos (coluna) values(' . $valor . ')');
, Логотип, предположим, что пользователю использовать приговор: 1); DROP TABLE Produtos;
для поля valor
команда будет выглядеть:
insert into Produtos (coluna) values(1); DROP TABLE Produtos;
Он будет вставлять новую запись, чье поле coluna
1
, а затем он будет удалять таблицы "Товары".
Как я могу улучшить мой код, чтобы предотвратить эту ситуацию?
9 answers
1 - НЕ используйте функции mysql_*, поскольку они считаются устаревшими (deprecated), и скоро будут удалены. несколько причин, чтобы не использовать их.
Используйте prepared statements, это позволит уменьшить уязвимость sql-инъекция, потому что запрос состоит из двух частей, команд sql и маркировка(?
и :nome
), которые будут поменять значениями, первый работает уже второй же содержащий инструкции корректный sql будет рассматриваться как текст.
Маркировка не могут заменены имена databases, таблицы/views, столбцы и значения в clásulas ORDER BY
, GROUP BY
.
Есть два драйвера, которые поддерживают это, o PDO и mysqli.
, Например, prepared staments, PDO:
$db = new PDO('mysql:host=localhost dbname=teste', 'usuario', 'senha');
$sql = 'INSERT INTO tabela(campo1, campo2, campo3) VALUES(?, ?, ?)';
$stmt = $db->prepare($sql);
$stmt->bindValue(1, 'valor1');
$stmt->bindValue(2, 'valor2');
$stmt->bindValue(3, 'valor3');
$stmt->execute(); // executa o insert ou outra sql
, Например, prepared staments mysqli:
$db = new mysqli('localhost', 'usuario', 'senha', 'teste');
$sql = 'INSERT INTO tabela(campo1, campo2, campo3) VALUES(?, ?, ?)';
$stmt = $db->prepare($sql);
if(!$stmt){
echo 'erro na consulta: '. $db->errno .' - '. $db->error;
}
$var1 = 1;
$var2 = 'foo';
$var3 = 1.99;
$stmt->bind_param('isd', $var1, $var2, $var3);
$stmt->execute();
String isd
соответствует типам данных прошлые являются integer, string, double b
blob поля в соответствии с ручного.
Существуют несколько способов предотвратить SQLInjection. Два примера:
- Функции mysql_real_escape_string php универсальное
- Prepared Statements способ действительно эффективный
Я Рекомендую вам прочитать на второй вариант и примите PDO для обработки базы данных.
Читайте также: mysql_real_escape_string() по сравнению с Prepared Statements
Не рекомендуется использовать библиотеку mysql будет прекращено в ближайшие версии.
Для задачи существует несколько решений:
Http://www.php.net/manual/pt_BR/class.pdo.php
Http://medoo.in/ это, что я использую. Уже много sql общий готова! Стоит проверить.
ПРИМЕЧАНИЕ: в библиотеке более быстрой mysqli, потому что под обе используют mysqli.
Просто не используйте string concatenation, используйте параметры SQL всегда, или библиотека, что-то сделать для себя.
И В вашем примере с параметра user вставить '1); DROP TABLE Продукты;' в столбце, если это позволяет, в противном случае получит сногсшибательному звуку.
И В моем framework я пытаюсь использовать NotORM для слоя данных, и предотвращает многие проблемы, связанные с SQL-инъекции, а также использует интерфейс PDO ;) http://pedrosimoes79.github.io/silverbullet/
И В случае NotORM используют PDO::quote
Http://www.php.net/manual/en/pdo.quote.php https://groups.google.com/forum/#!topic/notorm/3kR2o9iI5xQ
, Используя этот код в Model:
function getHelloworldMySQL()
{
$this->db->hello2->test->insert([
'text' => "'Hello with a drop'); DROP TABLE Produtos;"
]);
foreach ($this->db->hello2->test as $id => $hello) {
return $hello['text'];
}
}
И Получаем ;)
Я Нашел странным, никто не процитировать
Stored Procedure.
Кроме того, чтобы избежать SQL-Инъекции, вы получаете высокую производительность, поскольку они компилируются.
Create PROCEDURE stp_ExemploInsert
@nome varchar(200),
@idade smallint
as
BEGIN
Set nocount on; --não traz nenhum retorno de linha extra;
Insert tabela_exemplo (nome,idade) values (@nome, @idade)
END
Dai в PHP, и не помню, хорошо, но это было
$stmt = mssql_init('Nome_Procedure');
mssql_bind($stmt, '@nome','Felipe Pena', SQLVARCHAR,false,false,0);
mssql_bind($stmt, '@idade ',25,SQLINT2);
mssql_execute($stmt);
mssql_free_statement($stmt);
Http://php.net/manual/en/function.mssql-execute.php
ПРИМЕЧАНИЕ: Хранимые Процедуры является неуязвимым, если вы не делаете что-то!
CREATE PROCEDURE getDescription
@vname VARCHAR(50)
AS
EXEC('SELECT description FROM products WHERE name = '''+@vname+ '''')
RETURN
, псевдоним это ужас! Курсоры также могут быть опасными для SQL инжектор, но это намного сложнее.
- хороший способ предотвратить инъекции SQL также уже с помощью готовых решений для этого.
Возможно, использование Frameworks Full Stacks
- что, уже есть несколько готовых решений для программиста от проверок до безопасности - чтобы помочь в защите вашего приложения.
Случае не будет необходимости использования Framework Full Stack
, я хотел бы выбрать для использования framework для абстракции базы данных (средств orm способом сопоставления), как Doctrine 2
.
Я Говорю это, потому что Рамок как правило, предназначены также для этого типа относятся: безопасность.
Кроме того, прекратить использование библиотеки запрещены, как уже было сказано, в качестве ответа, вы должны проверить свои запросы, чтобы иметь возможность проверить, если какой-либо из них проходит что-то чувствительное, без шифрования, если какой-либо форме его переживает, методы, GET etc.
Есть несколько методов, чтобы можно было предотвратить только от вас зависит, найти, какой из них будет лучше в вашем случае и использовании.
Вы Можете использовать вместе с prepared statements
функция filter_var()
. Но тихо, filter_var
имеет несколько назначений, например:
filter_var('[email protected]', FILTER_VALIDATE_EMAIL);//retorna boolean true
filter_var('[email protected]\\', FILTER_SANITIZE_EMAIL);//retorna string "[email protected]"
Вы можете взглянуть на документации подход, о SQL-инъекции, которые вы не найдете стороны, только от взгляда на константы, которые могут быть использованы.
Я использую framework, Doctrine ORM для уровня данных. Каркасы во избежание SQL-инъекции.
На обзор Doctrine: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/getting-started.html, охватывающих установки с помощью composer и пример основы объектно-Реляционного Отображения.
На ваш вопрос, с помощью вставки продукции, документации есть пример того, на тот же случай. Это просто, и вы находится под защитой.
<?php
use Doctrine\ORM\Annotation as ORM;
/**
* @ORM\Entity @ORM\Table(name="products")
**/
class Product
{
/** @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue **/
protected $id;
/** @ORM\Column(type="string") **/
protected $name;
// .. (other code)
}
Вставка:
<?php
// create_product.php <name>
require_once "bootstrap.php";
$newProductName = $argv[1];
$product = new Product();
$product->setName($newProductName);
$entityManager->persist($product);
$entityManager->flush();