Hi all I need to use Prepared Statements in my site. I tried use this
$sql = "SELECT * FROM tbl_user WHERE uid=:id and activation_key=:key";
$query = $this->db->query(
$sql,
array( ':id' => $uid ,':key' => $activation_key)
);
but this is not working. When I change :id and :key to ? its working.
CodeIgniter does not support Prepared Statements. If you look at the sourcecode for CI's Database class, you will see that they resolve bindings simply by replacing the question marks with the data from the passed array:
https://github.com/EllisLab/CodeIgniter/blob/develop/system/database/DB_driver.php#L874
They only support Query Binding with unnamed placeholders. See http://ellislab.com/codeigniter/user-guide/database/queries.html
Query Bindings
Bindings enable you to simplify your query syntax by letting the system put the queries together for you. Consider the following example:
$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?";
$this->db->query($sql, array(3, 'live', 'Rick'));
The question marks in the query are automatically replaced with the values in the array in the second parameter of the query function.
and http://ellislab.com/forums/viewthread/105112/#528915
Even though CI doesn’t support prepared statements, it does support Query Bindings. With prepared statements you have to call some type of prepare() function and then some type of execute() function. With query bindings, you only have to call one function and it basically does the same thing. Because of this, I like query bindings better than prepared statements.
On a sidenote, changing ? to :foo is merely changing from unnamed to named bindings (which CI apparently does not support either). Just because you use either or doesn't mean you are preparing the statements.
I came across this question as I faced a similar issue. The answer is correct that CI doesn't support prepared statements. However it doesn't mean that you can't use prepared statements!
In the following example I am using PDO as my connection class but the following code will work:
$q = $this->db->conn_id->prepare('SELECT * FROM tbl_user WHERE uid=? and activation_key=?');
$q->execute(array($param1,$param2));
print_r($q->fetchAll());
Note the conn_id is the PDO object against which you can run your prepared statements.
What this won't allow however is for you to get the query string which the native CI functions allow. You will need something like Get Last Executed Query in PHP PDO for that.
Further more however this doesn't stop you using the Query Builder to build your statements which you can then use in the PDO prepare. For example -
$db->where('uid = ?',null,false);
$db->where('activation_key = ?',null,false);
$q = $this->db->conn_id->prepare($db->get_compiled_select('tbl_user'));
Would build the query and would allow you to see the basic query if you output $db->get_compiled_select('tbl_user');
As #site80443 points out, CI4 now supports prepared statements and this can be found here:
https://codeigniter.com/user_guide/database/queries.html?highlight=prepared#prepared-queries
Related
I am trying to use the mysqli prepare and bind_param but it is not working. The bind_param function is not doing anything, not returning any error, and pauses execution of the rest of my codes. My codes are as follows:
$set = mysqli_fetch_array($sett);
$vxemail = $_SESSION['email'];
$profv = $flash->prepare("SELECT * FROM `user` WHERE `email`=:em");
$profv->bind_param(':em',$vxemail);
If you need named query parameters like :em then you should use PDO, not mysqli.
PDO supports both named parameter placeholders and positional parameter placeholders. This is handy because some databases like Oracle normally support only named placeholders, while MySQL supports only positional placeholders. PDO translates one style to the other transparently, so you can use both.
(Just don't mix different types of placeholders in the same query. Choose one style or the other.)
I prefer PDO for reasons like this. It has a lot of nice features that make it better than Mysqli.
use this code
$set = mysqli_fetch_array($sett);
$vxemail = $_SESSION['email'];
$profv = $flash->prepare("SELECT * FROM user WHERE email=?");
$profv->bind_param('s', $vxemail);
bind_param accepts the first parameter type, and then the transmitted data.
for example:
$profv->bind_param('ssid', $name, $lastname, $age, $amount);
s = string, i = integer, d = double
I am new to the PDO class, I have been using MYSQLI since just now and I am kind of confused. This question is rather simple but I cannot find the answer in straight text anywhere in the manual. So calling $pdo->query(some query) will automatically escape the query and will not leave any room for potential injections of any kind. Is this true?
NO, this is NOT true.
To avoid any risk of mysql injections you will need either prepared statments or to escape properly your variables (which would involve you to manually escape each variable before submit). I would suggest to use prepared statements because they are way easier to use. Please read this post How can I prevent SQL injection in PHP?. You can either have those with mysqli OR PDO, a nice example of PDO prepared statments, token from stackoverflow
$id = 1;
$stm = $pdo->prepare("SELECT name FROM table WHERE id=?");
$stm->execute(array($id));
$name = $stm->fetchColumn();
You can learn more here about PDO prepared statements. I would also like you to have a look here How can prepared statements protect from SQL injection attacks?
the query function is not safe.
you better use prepare of the PDO object.
e.g.
$sth = $dbh->prepare("select * from mytable where myattr = :attr");
the $sth handler can be used to set the placeholder in your query (e.g. :attr in this example)
you have two choice :
either you use an array directly in the execute function of the handler :
$sth->execute (array ('attr', $myattr));
or the bindParam function of the handler then execute
$sth->bindParam ('attr', $myattr);
$sth->execute();
The method provide a good way of escaping the single quotes in your arguments.
note : also take a loot at Why you Should be using PHP’s PDO for Database Access (net.tutsplus.com)
No, PDO::query is just as vulnerable as mysql_query or any other raw query method.
If you do
$sql = "SELECT foo FROM bar WHERE baz = '$var'";
and $var is
Robert'; DROP TABLE users; --
so the result is
SELECT foo FROM bar WHERE baz = 'Robert'; DROP TABLE users; --'
then no API can help you, because no API can tell the difference between what the query part and what the user value is. This difference is only clear to the API when you use prepared statements or escape special characters in the value properly.
Read The Great Escapism (Or: What You Need To Know To Work With Text Within Text).
I'm building simple query builder, and I have two questions:
Is it possible to secure mysql queries with normal functions to the similar level as it is done using ->execute(array(':param:' => ... ?
Is it possible to use many variables in one query, give them the same names (the ones after the semicolon), and then bind them one by one?
If I understand you correctly, you would like to know if it possible to replicate the functionality of bindParam with the standard mysql_* functions?
Short answer is no. Please do not use the mysql functions at all, use mysqli or PDO as these provide you with the true security when it comes to prepared statements. They can also provide much better query performance as the SQL is able to be pre-optimised for the database.
You will have to define each parameter separately (even if it is the same value). You could also pass a simple array to the execute() method call, but you do not then have the option to explicitly define the parameter types.
Within your function use some thing like this:
$name = "fred";
$statement = $pdo->prepare("SELECT id FROM contacts WHERE first_name = ? OR last_name = ?");
for ($x = 1; $x <= 2; $x++) {
$statement->bindParam($x, $name, PDO::PARAM_STR);
}
$statement->execute();
I have heard that using PREPARE and EXECUTE in a SQL statement will sanitize user-supplied data into something incapable of SQL injection. Is this true?
My original query is this:
$query =
"SELECT * FROM sales_orders
WHERE ksisoldby ILIKE '".$user."'";
This is my best guess for changing it to a prepare/execute statement:
<?php
$id = $_POST['id'];
$search = $_POST['user_supplied_search_term'];
PREPARE search_query_function (varchar, varchar) AS
SELECT * FROM sales_orders
WHERE ksisoldby ILIKE '$1'";
EXECUTE search_query_function($id, $search);
?>
Is this written/invoked correctly? There are also some built in php objects (PDO) that I have read about. Should I be using those instead or in conjunction? Thanks for help on this sort of broad question.
You incorporate prepare() and execute() in PHP by using prepared statements, which are available when you use PDO. This extensions is responsible for creating the appropriate PREPARE and EXECUTE statements for your database according to the database driver you have selected.
Here is an example adapted from the PHP manual using prepare() and execute().
$sth = $dbh->prepare('SELECT * FROM sales_orders
WHERE ksisoldby ILIKE ?');
$sth->execute( array( $_POST['user_supplied_search_term']));
This will take care of the parameter escaping for you and create an SQL statement similar to:
SELECT * FROM sales_orders
WHERE ksisoldby ILIKE 'something'
So you need to adapt the above code to include your SQL statement within the call to prepare(), which requires you to add placeholders to where you want your parameters to be included. Then you call execute(), which will add in the values passed to it.
You could also use pg_query_params, easy to use and safe.
PHP's PDO allows multiple querys to be executed at once, either via the query() method or as a prepared statement. Both of the following examples work:
// Two SQL queries
$query = "SELECT * FROM table; DROP table;"
// Execute via query()
$pdo->query($query);
// Execute via prepared statement
$stmt = $pdo->prepare($query);
$stmt->execute();
Is there any way to limit PDO to a single query at a time, much like the mysql_query() function is?
This is a more up-to-date answer to this question.
The old way of preventing multi query execution was to disable emulated prepares, however this was only applicable to the PDO::prepare() method. In newer versions of PHP (>= 5.5.21 and >= 5.6.5), a new constant has been introduced to disable this multi query execution in both PDO::prepare() and PDO::query(). (Constants aren't usually added in patch versions, but this was done due to the severity of a Drupal SQL injection attack brought about by this capability).
The new constant is PDO::MYSQL_ATTR_MULTI_STATEMENTS and must be set on object creation (as the fourth argument to the PDO constructor) - setting it on a pre-existing object with PDO::setAttribute() will not work.
$pdo = new PDO('mysql:host=_;dbname=_', '', '', [PDO::MYSQL_ATTR_MULTI_STATEMENTS => false]);
Mmm, there's a way of achieving this by disabling the emulation of prepared statements in PDO to make it use the native mysql API instead (multi-querying is not supported in server-side prepared statements):
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
However, one of the drawbacks of this option is that the query cache is lost.