This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 11 months ago.
I want to see if my practice is good enough to protect from sql injection.
$mysqli = new mysqli($host,$username,$password,$database);
$query = $mysqli->prepare('SELECT * FROM users WHERE id = ? AND check = ?');
$query->bind_param('ii', $_GET['id'], $_POST['check']);
$query->execute();
$result = $mysqli->query($query);
while ($row = $result->fetch_assoc()) {
...
}
I've seen that in some examples have this line before the while:
$result = $query->get_result();
And others that use trim(), intval() etc in $_GET/$_POST for safety.
Which is the best practice and safest way to avoid sql injections?
The best MySQLi prepared statement practice is apparently a PDO prepared statement
the code you posted above just makes no sense. To make it work, indeed you have to use get_result() function, which - alas! - is not guaranteed to be available:
$query = $mysqli->prepare('SELECT * FROM users WHERE id = ? AND check = ?');
$query->bind_param('ii', $_GET['id'], $_POST['check']);
$query->execute();
$result = $query->get_result();
while ($row = $result->fetch_assoc()) {
...
}
while with PDO you need two times less code which is always guaranteed to work
$query = $pdo->prepare('SELECT * FROM users WHERE id = ? AND check = ?');
$query->execute([$_GET['id'], $_POST['check']]);
while ($row = $query->fetch()) {
...
}
not to mention other PDO's wonderful features
And others that use trim(), intval() etc
these things are just irrelevant it SQL, you may use them for whatever else reason.
Related
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 5 years ago.
I just want to check how safe (if at all) my PHP-MYSQL queries are, I'm using user data which is coming through $_POST and then validating - the validation process of all data includes using mysqli_real_escape_string() on the string and trim(). The nature of some of my inputs however means that I don't restrict any characters on user input. Is what I'm doing safe and if not how could it be improved.
An example of an insert query (where $name and $description are $_POST data values which have been through a validation function.)
$sql = "INSERT INTO company(company_name, company_description) VALUES('".$name."', '".$description."')";
$result = mysqli_query($con, $sql);
An example of a select query (where $companyid is user input, real_escaped and stripped)
$sql = "SELECT * FROM events WHERE event_company=".$companyid."";
$result = mysqli_query($con, $sql);
Thanks in advance.
Here are your queries updated to use mysqli prepared statements.
$sql = "INSERT INTO `company` (`company_name`, `company_description`) VALUES(?, ?)";
$stmt = $con->prepare($sql);
$stmt->bind_param('ss',$name,$description); // ss is for string string
$stmt->execute();
$result = $stmt->get_result();
and
$sql = "SELECT * FROM `events` WHERE `event_company` = ?";
$stmt = $con->prepare($sql);
$stmt->bind_param('i',$companyid); // i indicates integer
$stmt->execute();
$result = $stmt->get_result();
There a type of hack called "SQL INJECTION" which can deceive your control. Read there for more information https://www.veracode.com/security/sql-injection
I'm sorry if this is a duplicate question but I don't know how to solve my problem. Every time I try to correct my error I fail. My code is:
if (isset($_GET["comment"])) {$id = $_GET["comment"];}
$query = "SELECT * FROM posts WHERE id = {$id['$id']};";
$get_comment = mysqli_query($con, $query);
Can anybody correct the code to not show an error anymore and tell me what did I wrong?
Try this:
$id = isset($_GET['comment']) ? $_GET['comment'] : 0;
$query = "SELECT * FROM `posts` WHERE `id` = " . intval($id);
The use of intval will protect you from SQL injection in this particular case. Ideally, you should learn PDO as it is extremely powerful and makes prepared statements much easier to handle to prevent all injections.
An example using PDO might look like:
$id = isset($_GET['comment']) ? $_GET['comment'] : 0;
$query = $pdo->prepare("SELECT * FROM `posts` WHERE `id` = :id");
$query->execute(array("id"=>$id));
$result = $query->fetch(PDO::FETCH_ASSOC); // for a single row
// $results = $query->fetchAll(PDO::FETCH_ASSOC); // for multiple rows
var_dump($result);
First of all you should prevent injestion.
if (isset($_GET["comment"])){
$id = (int)$_GET["comment"];
}
Notice, $id contanis int.
$query = "SELECT * FROM posts WHERE id = {$id}";
Assuming your $id is an integer and you only want to make the query if it is set, here's how you could do it using prepared statements, which protect you from MYSQL injection attacks:
if (isset($_GET["comment"])) {
$id = $_GET["comment"];
$stmt = mysqli_prepare($con, "SELECT * FROM posts WHERE id = ?");
mysqli_stmt_bind_param($stmt, 'i', $id);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $get_comment);
while (mysqli_stmt_fetch($stmt)) {
// use $get_comment
}
mysqli_stmt_close($stmt);
}
Most of these functions return a boolean indicating whether they were successful or not, so you might want to check their return values.
This approach looks a lot more heavy duty and is arguably overkill for a simple case of a statement containing a single integer but it's a good practice to get into.
You might want to look at the object-oriented style of mysqli which you might find a little cleaner-looking, or alternatively consider using PDO.
When I use something like this:
$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
}
according this answer:
How can I prevent SQL injection in PHP?
I get this error:
Call to undefined method mysqli_stmt::get_result()
Because get_result is available only with mysqlnd (get_result php reference).
So is there any alternative how to get all columns? If I don't want bind all columns(using bind_result()), because in my case I do query on 3 tables and I just dont want bind all columns because it is an insane job.
So I don't want use bind_result(), get_resuslt doesn't work is there any alternative or it means I cant use prepared statements and only chance is get back to this:
sql = "SELECT * FROM ...." //just some query
$query = mysqli_query($db_donnection, $sql);
while ($row = mysqli_fetch_array($query, MYSQLI_ASSOC)) {
$id = $row["id"];
$e = $row["email"];
//....
}
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
PHP changing old mysql_query to PDO
(4 answers)
Closed 9 years ago.
I am only having my very first attempt to use the new method, since I was advised to begin using PDO method to instead of the old one for querying the DB.
I cannot figure out how to place the variable into it as I was doing previously with my old one.
here is an old version of my script
$file_code = filter_input( INPUT_GET, 'fileid' );
$res = mysql_query("SELECT * FROM `Files` WHERE `fileID`='".$file_code."'") or die ( mysql_error() );
if(mysql_num_rows($res) == 0)
{
die(header("Location: error.php"));
}
$info = mysql_fetch_assoc($res);
and here is my attempt to use the new way to achieve the same result
$file_code = filter_input( INPUT_GET, 'fileid' );
$db = new PDO($host,$db_name,$db_user,$db_pass);
$res = $db->prepare('SELECT * FROM Files WHERE fileID = :".$file_code."');
Can you please help me with it since I am not a PRO in php
Thanks in advance
$res = $db->prepare('SELECT * FROM Files WHERE fileID = :".$file_code."');
What you are doing here is really negating the whole concept of prepared statements.
This is what you should do:
$res = $db->prepare('SELECT * FROM Files WHERE fileID = ?');
$res->execute(array($file_code));
$data=$res->fetchAll();
The beauty of prepared statements is in the fact that you don't need to escape your variables and it's also more efficient if you run it more times.
$file_code = filter_input(INPUT_GET, 'fileid');
$db = new PDO("mysql:host=$host;dbname=$dbname;","login","pass");
$res = $db->prepare('SELECT * FROM Files WHERE fileID = ?')
->execute(array($file_code));
$result = $res->fetchAll();
There is two ways:
$stmt = $db->prepare('SELECT * FROM Files WHERE fileID = :file_code');
$stmt->bindParam(':file_code', $file_code);
$stmt->execute();
Or
$stmt = $db->prepare('SELECT * FROM Files WHERE fileID = :file_code');
$stmt->execute(array(':file_code' => $file_code));
So you may run PDOStatement::bindParam to pass your values or pass them as an array right to the PDOStatement::execute. The first one is much more flexible.
I know that I need prepared statements because I make more than one call to my database during one script.
I would like to get concrete examples about the following sentence
Look at typecasting, validating and sanitizing variables and using PDO with prepared statements.
I know what he mean by validating and sanitizing variables. However, I am not completely sure about prepared statements. How do we prepare statements? By filters, that is by sanitizing? Or by some PDO layer? What is the definition of the layer?
What do prepared statements mean in the statement? Please, use concrete examples.
What do prepared statements mean in
the statement?
From the documentation:
This feature allows commands that will be used repeatedly to be parsed and planned just once, rather than each time they are executed.
See pg_prepare
Example from the page linked above:
<?php
// Connect to a database named "mary"
$dbconn = pg_connect("dbname=mary");
// Prepare a query for execution
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');
// Execute the prepared query. Note that it is not necessary to escape
// the string "Joe's Widgets" in any way
$result = pg_execute($dbconn, "my_query", array("Joe's Widgets"));
// Execute the same prepared query, this time with a different parameter
$result = pg_execute($dbconn, "my_query", array("Clothes Clothes Clothes"));
?>
The MySQL documentation for Prepared Statements nicely answers the following questions:
Why use prepared statements?
When should you use prepared
statements?
It means it will help you prevent SQL injection attacks by eliminating the need to manually quote the parameters.
Instead of placing a variable into the sql you use a named or question mark marker for which real values will be substituted when the statement is executed.
Definition of PDO from the PHP manual:
'The PHP Data Objects (PDO) extension defines a lightweight, consistent interface for accessing databases in PHP.'
See the php manual on PDO and PDO::prepare.
An example of a prepared statement with named markers:
<?php
$pdo = new PDO('pgsql:dbname=example;user=me;password=pass;host=localhost;port=5432');
$sql = "SELECT username, password
FROM users
WHERE username = :username
AND password = :pass";
$sth = $pdo->prepare($sql);
$sth->execute(array(':username' => $_POST['username'], ':pass' => $_POST['password']));
$result = $sth->fetchAll();
An example of a prepared statement with question mark markers:
<?php
$pdo = new PDO('pgsql:dbname=example;user=me;password=pass;host=localhost;port=5432');
$sql = "SELECT username, password
FROM users
WHERE username = ?
AND password = ?";
$sth = $pdo->prepare($sql);
$sth->execute(array($_POST['username'], $_POST['password']));
$result = $sth->fetchAll();
How do we prepare statements:
You define a query one time, and can called it as often as you like with different values. (eg. in a loop)
$result = pg_prepare($dbconn, "my_query", 'SELECT * FROM shops WHERE name = $1');
$result = pg_execute($dbconn, "my_query", array("Joe's Widgets"));
$result = pg_execute($dbconn, "my_query", array("row two"));
$result = pg_execute($dbconn, "my_query", array("row three"));
see: http://us2.php.net/manual/en/function.pg-execute.php
Reply to Karim79's answer
This
$result = pg_prepare($dbconn, "query1", 'SELECT passhash_md5 FROM users WHERE email = $1');
seems to be the same as this
$result = pg_prepare($dbconn, "query1", 'SELECT passhash_md5 FROM users WHERE email = ?');
Conclusion: the use of pg_prepare and pg_execute makes PHP much more efficient, since you do not need to consider sanitizing. It also helps you in the use of PDO.