Mysqli prepared statement for non dynamic variable - php

I'm learning mysqli prepared statements and have a few questions about it
From what I have understood we use prepared statement for those queries that have dynamic variable in them for eg in login - email & password.
I want to know if prepared statements are necessary for queries where no dynamic element is there for eg fetching users from database. If I do this like below query does this makes it vulnerable
SELECT
name, email
FROM
users
How can I use prepared statement without using bind param?
Like in pdo we do like this
$array=array($email,$pass);
$db->query("SELECT name from users where email=? and password=?");
$db->execute($array);
Can I do something like this in mysqli? I have searched and found results that use bind param , nothing without using bind.?

Your answers are as follows:
1.See this-stackoverflow.com/questions/5108414/mysqli-query-vs-prepare-(the link that AdRock posted in his comment.)
2.Instead of-
$db->query("SELECT name from users where email=? and password=?");
$db->bind_param("ss", $email, $password);
$db->execute($array);
You can do this-
$db->query("SELECT name from users where email='$email' and password='$password'");
$db->execute($array);

Related

Is it necessary to use a prepared statement for a select statement without user input?

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.

SELECT within SELECT PDO prepared statement [duplicate]

This question already has answers here:
Are PDO prepared statements sufficient to prevent SQL injection?
(7 answers)
Closed 7 years ago.
I'm thinking of an example like this one:
The request hits a page at an url (by whichever means), with a parameter. example.com/api/page?name=bob. It's my understanding that you should do a prepared statement to get the $_POST[name]parameter and make sure it's not anything funky, but it does so by evaluating the expression.
My first question is: How does it do so (evaluate the expression)?
My second question is:
What if a user inputs something along the lines of "SELECT * FROM users" or "DROP TABLE users" that gets passed to the $_POST['name'] parameter (the ?name=bob at the end), what would happen in that case?
Just as an example, the final query would be something like
SELECT name, continent FROM world
WHERE continent IN
(SELECT continent FROM world WHERE name='Brazil')
the second select acting as the user input parameter - so $_POST['name'] contains this query SELECT continent FROM world WHERE name='Brazil'
Lastly, the third question i have is how can i protect against something like that?
I'm guessing PDO is design specifically to prevent query within query(?), but after reading around a bit i'm still quite confused.
I'm still learning all of this so if i'm not clear or specific enough in my inquiry please let me know, and i'll try and address that.
EDIT:
To clear any confusion, what i'm doing is this:
$pdo = new PDO('..');
$sql = 'SELECT id FROM users WHERE username = :username';
$statement = $pdo->prepare($sql);
$statement->bindParam(':username', $_POST['username']);
Question is, what if $_POST['username'] contains 'SELECT * FROM users' (or any other query) ?
How does prepare() work? Can what i described actually present a security hole? I need some help in understanding this.
To clear any confusion, what i'm doing is this:
$pdo = new PDO('..');
$sql = 'SELECT id FROM users WHERE username = :username';
$statement = $pdo->prepare($sql);
$statement->bindParam(':username', $_POST['username']);
Question is, what if $_POST['username'] contains 'SELECT * FROM users' (or any other query) ?
This query would return the ids of all users with the username "SELECT * FROM users".
By passing $_POST['username'] as parameter the database knows that whatever string $_POST['username'] may contain it is NOT part of the query. It's just a string.
This prevents SQL injection since the parameter will NOT be executed. This also means that
SELECT name, continent FROM world
WHERE continent IN
(SELECT continent FROM world WHERE name='Brazil')
the second select acting as the user input parameter - so $_POST['name'] contains this query SELECT continent FROM world WHERE name='Brazil'
won't work. Because you can't include queries in parameters. Well you can but they will not be executed.

Prepared Statements - Should I use php prepared statements even in queries without (?) placeholders?

It makes perfect sense to me to use prepared statements in a query of the following type:
$sqlQuery = "SELECT phone FROM contact WHERE name = ? ";
However, in the following situation, does it make sense and is it useful to use prepared statements, as sometimes seen?
$sqlQuery = "SELECT name FROM contact";
Thanks in advance
If you are running a query without any user-entered variables, you can just do:
$db->query("SELECT name FROM contact")
As soon as you start entering in user-inputted data, then you need to use a prepared statement.
$db->prepare("SELECT phone FROM contact WHERE name = ?");
Generally, prepared statements only need to be used when user input is concerned. It's perfectly fine to use them in situations when no user input is concerned as well - If you're using PDO you may find it more convenient to use the same PDO connection string and query process as before, as using a different function set would require you to reopen the connection.

Use a variable twice in prepared statement

I'm beginning to use prepared statements with my sql queries in php and in starting with this I have come up with a question.
I have a function that grabs a user's id from a table at login. I want the user to be able to use either their username or email address for their login.
So my sql statement is:
SELECT * FROM `login` WHERE `username`=? OR `emailAddress`=?
Now essentially when in this query username and emailAddress will be the same because it can be either or.
So when binding my statements do I bind my variable twice:
bind_param('ss', $user, $user);
So the value for username and emailAddress needs to be the same. Essentially I want $user to be the value of both the placeholders.
My questions are: Am I doing this correctly? Is there a more efficient way?
Yes, you would have to bind it twice. If you are opposed to that for some reason, you could rephrase the query as:
SELECT *
FROM `login` l cross join
(select ? as thename) const
WHERE l.`username` = thename OR `emailAddress` = thename;
This is using a subquery to name the parameter so it can be referred to multiple times in the query.
Yes. There have to be as many variables in the bind_param() call as there are placeholders in the query. Consider if you had:
SELECT * FROM login
WHERE username = ? and emailAddress = ? and country = ?
and you tried to bind too few of them:
bind_param("ss", $user, $country);
How is it supposed to know which variable should be repeated for the extra placeholder?
There's no problem with using the same variable twice. I wouldn't recommend it with bind_result, though -- it will presumably allow it, but I don't know if it's predictable which column will be put into the variable.

PDO Prepare statement not processing parameters

I've exhausted all efforts at what appears to be a trivial problem, but gotten nowhere.
There is a simple Prepare statement:
$qry = $core->db->prepare("SELECT * FROM users WHERE email = '?'");
$qry->execute(array('email#address.com'));
However, no rows are returned. Running the query with the parameters hardcoded into the query results in a successful selection of one row. I've tryed many different methods of doing the prepare, but even it this most simple form it isn't working.
The PDO object is stored in a singleton called Core. PDO is using the mysql driver.
Remove quotes from the query:
("SELECT * FROM users WHERE email = ?");
The reason to use placeholders (? symbol) is to forget about quotes. PDO will add them automatically.

Categories