What is the best way to prevent SQL injection in php

  • 2020-06-12 08:43:21
  • OfStack

If the user enters a query inserted directly into an SQL statement, the application is vulnerable to SQL injection, as in the following example:


$unsafe_variable = $_POST['user_input'];
mysql_query("INSERT INTO table (column) VALUES ('" . $unsafe_variable . "')");

This is because the user can enter something like VALUE "); DROP TABLE table; -, turns the query into:

INSERT INTO table (column) VALUES('VALUE'); DROP TABLE table;'

How can we prevent this? Please see the following
Use prepared meaning statements and parameterized queries. sql statements with any parameters are sent to the database server and parsed! It is not possible for an attacker to maliciously inject sql!
There are basically two options for achieving this goal:
1. PDO(PHP Data Objects) :

$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array(':name' => $name));
foreach ($stmt as $row) {
    // do something with $row
}

2. Use mysqli:

$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    // do something with $row
}

PDO(PHP Data Object)
Note that when using PDO to access the MySQL database the actual prepared meaning statements are not used by default! To solve this problem, you must disable the simulation of prepared statements.
Examples of creating connections using PDO are as follows:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');
$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

The error pattern ERRMODE is not strictly required in the above example, but it is recommended that it be added. This method script does not stop when a run error results in a fatal error. And give the developer the opportunity to catch any errors (when an PDOException exception is thrown).
The setAttribute() line 1 is mandatory and tells PDO to disable the simulated prepared meaning statement and use the real prepared meaning statement. This ensures that statements and values are not parsed by PHP before being sent to the MySQL database server (there is no opportunity for an attacker to inject malicious SQL).
Of course you can set character set parameters in the constructor options, especially since the 'old' VERSION of PHP (5.3.6) omitted character set parameters in DSN.

Explanation (explanation)
What happens when the sql prep statement you pass is parsed and compiled by the database server? By specifying the character (in the above example like a? Or name) tells the database engine what you want to filter, and then calls execute to execute the combination of the prepared statement and the parameter values you specify.

Here the most important of all, the parameter value is and precompiled statements, rather than a SQL string. SQL injection works created through deception SQL scripts include malicious string sent to the database. Therefore, by sending the actual separate sql parameters, you can reduce risk. Using a prepared statement, you send any parameters, will only be regarded as a string (although the database engine would do 1 parameter optimization, may of course end up to digital). In the example above, If the variable $name contains 'sarah'; DELETE * FROM employees, the result will only be 1 search string "sarah'; DELETE * FROM employees", you won't get an empty table.

Another benefit of using prepared statements is that if you execute the same statement multiple times in the same session, this will only be parsed and compiled once, giving you a bit of speed increase.
Well, since you ask how to insert, here's an example (using PDO) :


$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');
$preparedStatement->execute(array(':column' => $unsafeValue));


Related articles: