I coded these two blocks of code, but they seem to do the same. I don't understand when you should use each one of these.
$query= $db->query("SELECT * FROM forum_table WHERE forum_id = '$id'");
and
$sql="SELECT * FROM forum_table WHERE forum_id = '$id'";
if ($query = $db->prepare($sql))
$query->execute();
I don't get how those differ
Well, In case of
$query= $db->query("SELECT * FROM forum_table WHERE forum_id = '$id'");
This is very simple and known to all, simple a query executing directly as it is, no extra magic in it.
$sql="SELECT * FROM forum_table WHERE forum_id = '$id'";
if ($query = $db->prepare($sql))
$query->execute();
While in your second piece of code you have used the same query but you have prepare the query before executing (which you are not doing the right way, that is you are not leaving the placeholders to bind parameters to it,which is what the recommended and purposeful way of using prepared statements.),
By making placeholders in prepared statements for binding parameters to it later prepare actually make a template before actual execution of the query which helps in many ways.
Prepared statements reduces parsing time as the preparation on the query is done only once (although the statement is executed multiple times).
Note: It is best practice to bound parameters into the prepare statement so that if the query has to run multiple time with different parameters.Only
Bound parameters minimize bandwidth to the server as you would need to send only the parameters each time, and not the whole query.
Last but not the least, Prepared statements are very useful against SQL injection if parameters are bind to it.
For a start both of those statements are exactly the same so there is literally no difference.
There is a hint at something very different going on with the second block.
prepared statements
As for when to use one over the other.. always use prepared statements
Related
I have read a lot of PHP sql examples that use MySQL. I often see queries like this that have placeholders for values:
$query = “INSERT INTO users
(username, firstname, lastname, salutation, countrycode)
VALUES(:1, :2, :3, :4, :5)”;
Notice the values are :1, :2 etc.
I use the standard PHP module for postgres in PHP. My queries inject variables names like this:
$query = “INSERT INTO users(username)
VALUES($hello)”;
How do I use the same placebolder technique with postgres in PHP? Is it possible?
Prepared queries cause two database communication roundtrips instead of one: one for prepare, one for execute. If you want to reuse the same query many times, yet only parse it once, they will be faster, but if you want to use the query once, they will be slower. Basically, prepared queries are the wrong answer to your problem ; the correct answer is parameterized queries.
$result = pg_query_params($dbconn,
'SELECT * FROM users WHERE first_name = $1 AND last_name=$2',
array($firstname,$lastname));
This pg-specific function makes a parameterized query where placeholders of the form $number are replaced by the parameters with the corresponding one-based index in the array. Parameters are properly handled, and there is no risk of SQL injection.
I'm working on an application at the moment that uses PDO with a MySQL database.
I'm seeing some queries, which are just very simple SELECT statements, e.g.
SELECT * FROM table ORDER BY name ASC
The code does not use prepare, for example:
$sql = "SELECT * FROM " . $this->table . " ORDER BY name ASC";
$stmt = $this->db->query($sql);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $results;
Is it ok to do this, i.e. without using prepare, if there's no placeholders in the query?
The reason I've asked this is because according to the documentation it says
The SQL statement can contain zero or more named (:name) or question mark (?) parameter markers
which makes me wonder why you'd use this in the case of having no (zero) parameter markers?
Yes, because the use of prepared statements have 2 main causes:
Enhance running the same query with different parameters.
Prevent sql injection by separating sql code from the parameters.
Since you have no parameters that could be handled by a prepared statement (table names cannot be a parameter), you do not gain anything by pushing the query through as a prepared statement.
You still need to make sure that whatever is returned by $this->table will not cause any issues with the generated sql code.
Of course you can omit prepare if there is no dynamic data in your query.
But prepared statements have more advantages than only securing your queries.
According to http://php.net/manual/en/pdo.prepared-statements.php a second advantage is, that statements can be prepared once and executed multiple times.
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. For complex queries this process can take up enough time that it will noticeably slow down an application if there is a need to repeat the same query many times with different parameters. By using a prepared statement the application avoids repeating the analyze/compile/optimize cycle. This means that prepared statements use fewer resources and thus run faster.
Nevertheless, if you run your query only once and there is no dynamic data inside your query, omitting prepare is also fine.
In reality, you have to run such a query extremely seldom. A few tables with configuration-like options may be.
In all other cases at least LIMIT clause is obligatory.
So the question is rather a theoretical one.
At the start of my application, I check for the account status. This is an internal check I control as I provide the application on a sub-domain.
I have been using this:
// Retrieve account status for application
$query = "SELECT `client_account_status` FROM `version_control` WHERE id = '1' ";
However, as I adapt to prepared statements, I am curious if this is absolutely necessary when there is no user input to check?
$stmt = mysqli_stmt_init($link);
if (mysqli_stmt_prepare($stmt, 'SELECT client_account_status FROM version_control WHERE id = 1')) {
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $client_account_status);
mysqli_stmt_fetch($stmt);
mysqli_stmt_close($stmt);
}
Necessary, no. Recommended, yes. However the way your query is currently written you get no benefit from the prepared statement. Instead it should be:
mysqli_stmt_prepare($stmt,
'SELECT client_account_status FROM version_control WHERE id = ?'));
mysqli_stmt_bind_param($stmt, 'i', 1);
mysqli_stmt_execute($stmt);
The problem with your initial version is that mysql has no way of knowing what part of your query is a parameter and what part is the SQL statement. The point of parameterized queries is to clearly separate the statement from the parameters.
See How can I prevent SQL injection in PHP? for more information on preventing SQL injection.
No, it is not necessary when there is no user input. It can sometimes still be useful to use a prepared statement when there is input though, even if it's not user input. This is because preparing a statement allows it to be executed more efficiently if it is run lots of times with different data each time.
This question is going to have a lot of opinions, I'll add mine to the list...
I personally always go with PDO, or Doctrine's DBAL library.
A query using something like the DBAL class would happen as so:
$result = $db->fetchColumn('SELECT client_account_status FROM version_control WHERE id = :id', [
'id' => $id
]);
In PDO it can be as easy as so:
$pdo->prepare('SELECT client_account_status FROM version_control WHERE id = :id');
$result = $pdo->execute(array(':id' => $id));
It's always easy to read and it doesn't require you to write 5 lines of code every single time you want to do something with the database.
You can have both security and efficiency, and it seems given how you asked your question that you only want to avoid mysqli prepared statements out of the complexity and annoyance of writing so much code for so little to happen.
Recently one hacker tried to slow my website using sleep injection. Although we are using precautions like mysql_real_escape_string() to cover most of vulnerable inputs. We are passing id of the product through query string and it makes the command as:
$id = mysql_real_escape_string($_REQUEST['id']);
$qry = "Select * from products where id = ".$id;
but hacker tried to provide input as
?id=3 and sleep(4)
and query becomes
Select * from products where id = 3 and sleep(4);
Although there are some possible solutions like
Check if the product id is numeric or not
Remove word sleep from input using some customized function
Is there any other method to stop this? What is the best method to prevent sleep injections?
You are not escaping correctly. mysql_real_escape_string is for escaping SQL string syntax correctly, but you are simply embedding the value as bare value, not as SQL string. You need:
$qry = "SELECT * FROM products WHERE id = '$id'";
Note the quotes around the id in the query.
If the id is numeric though, casting to a number would be more sensible:
$id = (int)$_GET['id'];
The best method to prevent SQL injections is to use current technology. The MySQL mysql_ family of functions is deprecated and will be removed from PHP in a future revision.
You should use prepared statements with either MySQLi or PDO instead.
These technologies use prepared statements and parameterized queries. SQL statements are parsed by the database server separately from any parameters. It is impossible for an attacker to inject malicious SQL.
You basically have two options to achieve this:
MySQLi:
$stmt = $dbConnection->prepare('SELECT * FROM table WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
PDO:
$stmt = $pdo->prepare('SELECT * FROM table WHERE name = :name');
$stmt->execute(array(':name' => $name));
foreach ($stmt as $row) {
// do something with $row
}
What happens is that the SQL statement you pass to prepare is parsed and compiled by the database server. By specifying parameters (either a ? or a named parameter like :name) you tell the database engine what you want to filter on. Then when you call execute the prepared statement is combined with the parameter values you specify.
The important thing here is that the parameter values are combined with the compiled statement, not a SQL string. SQL injection works by tricking the script into including malicious strings when it creates SQL to send to the database. So by sending the actual SQL separately from the parameters you limit the risk of ending up with something you didn't intend. Any parameters you send when using a prepared statement will just be treated as strings (although the database engine may do some optimization so parameters may end up as numbers too, of course).
This is wrong question to ask.
"How to prevent mysql injections?" it has to be. Sleep or not sleep - it doesn't matter.
And there are plenty of answers on this question already
if you want a canonical one, then How can I prevent SQL injection in PHP?
if you want to understand, how it works, here I explained it in details
you should convert your queries into "prepared statements" using PDO or mysqli.
I was wondering if I should be using prepared statements for simple select queries?
Such as:
`SELECT * FROM `table_name`
With this, wouldn't it be better to just do:
$db->query('SELECT * FROM `table_name`');
If the query is only run once (per script) and there are indeed no variables in it, it indeed doesn't make much of a difference whether you use prepared statements or a one-off query.
#deceze is right. but if you want to used prepared statement use something like this,
<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if ($stmt->execute(array($_GET['name']))) // <== passed array of parameters
{
while ($row = $stmt->fetch())
{
print_r($row);
}
}
?>
As far as I think it is not a must, BUT you better do it for the integrity of the code. This simple select query (Which has no assignment) would not be able to attack.
If your table_name is a variable and not a hard coded item, you are protecting yourself from SQL injection.
The prepared statement separates the preparation (i.e. planning) and execution.
If you will be running the same query over and over again, then you are improving performance because you only plan the query once.
Performance loss of using a prepared statement over direct query for something like this, is virtually non-existent, because you open the connection either way, and the extra call that is done to execute is over the same connection.
Using * for selects if you plan to select only certain fields from a table, is likely to be as bad of a performance hit.