[Prevent SQL injection in PHP using prepared statements and PDO]
We can use prepared statements with PDO to prevent SQL injection in PHP. SQL injection occurs when a mixture of queries and data is sent to the database. In this approach, we do not specify the exact value of the data in the SQL statement. We use placeholders instead. Therefore, the parameterized SQL statement is sent to the server as the first request. We use prepare()
the function to achieve this. We bind the exact values of the parameters in the second request to the database server. For this we use bindValue()
the function. This way we send the program on the first request and the data on the second request. If we ask for data to be used with SQL code, the user can change the program and write malicious code. Therefore, it prevents malicious SQL code from being injected into the server.
For example, table users
contains the following fields and data.
+----+-----------+----------+------------+
| id | firstname | lastname | dob |
+----+-----------+----------+------------+
| 1 | bruce | rose | 1998-02-13 |
| 2 | jeff | james | 2000-03-30 |
+----+-----------+----------+------------+
It creates a variable $firstname
and assigns it a name bruce
. It creates the variable $sql
and writes a query on it SELECT * FROM users WHERE firstname =:fname;
.
firstname
Do not write exact data values for . Use parameters instead :fname
. Use $pdo
a variable to call a function on a query variable prepare()
. Replace :fname
the value of with the variable firstname
. Use execute()
the function to execute the statement. If the credentials match the database, fetch()
the result is checked using the function. If so, displays the id
, firstname
and for the selected row lastname
.
The following example demonstrates the use of prepared statements. It firstname
stores the value of the field in a variable to verify that the credentials match. If the variable contains some malicious code, it will display a message Credentials do no match
. This is because prepared()
the function only accepts parameterized queries, not exact data. $pdo
The variable contains the database connection object.
Sample code:
# php 7.*
<?php
$firstname = "bruce";
$sql = "SELECT * FROM users WHERE firstname =:fname ;";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(":fname", $firstname);
$stmt->execute();
if(!$result = $stmt->fetch(PDO::FETCH_OBJ)){
echo "Credentials do no match";
} else {
echo"Id: ".$result->id. " Name: ".$result->firstname." ".$result->lastname;
}
?>
Output:
Id: 1 Name: bruce rose
[Use parameterized query prepared
statements in PHP to prevent SQL injection]
We can prepared
use the statement with parameterized queries to prevent SQL injection in PHP. We mysqli()
create the database connection using the function object. In this approach, we use the question mark symbol ?
as a placeholder for data. We prepare()
use the function as the above method. We use bind_param()
the function to bind the real data into the placeholder. This method follows a similar working mechanism to the above method.
For example, establish a database connection, create a mysqli()
function object, and assign it to a variable $conn
. Assign the name jeff
to the variable $firstname
. Create variables $sql
and write queries SELECT * FROM FROM where where first name = ?;
. Use $conn
a variable to call a function on a query variable prepare()
. Replace placeholders for use ?
with variables $firstname
. Use execute()
the function to execute the statement. Call get_result()
the function and store the result in $result
a variable. If the condition fails, check if the row has num_rows
the attribute and use exit()
the function to return a message No Rows
. The method is called fetch_assoc()
and stored in the variable in the while loop $row
. id
Displays the , firstname
and for the selected row lastname
.
Sample code:
#php 7.x
<?php
$conn = new mysqli($host, $user, $pwd, $dbName);
$firstname = "jeff";
$sql = "SELECT * FROM users WHERE firstname = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $firstname);
$stmt->execute();
$result = $stmt->get_result();
if($result->num_rows === 0) exit('No rows');
while($row = $result->fetch_assoc()) {
echo"Id: ".$row['id']. " Name: ".$row['firstname']." ".$row['lastname'];
}
Output:
Id: 2 Name: jeff james
[ PDO::ATTR_EMULATE_PREPARES
Set the property to false
prevent SQL injection]
Using prepared statements in PDO may not be enough to prevent SQL injection if we do not set the PDO properties correctly. We should PDO::ATTR_EMULATE_PREPARES
set the property to false
prevent injection. If the property is set to true
, PDO will only emulate prepared statements without using them. Therefore, the system will be vulnerable to SQL injection attacks.
For example, $pdo
create a PDO connection to the database in the variable . Use this variable to call setAttribute()
the function. Set the property PDO::ATTR_EMULATE_PREPARES
to false.
Code example:
#php 7.x
<?php
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
?>