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.
Related
I have a web application which accepts user input, in this case having someone enter a username. I am preparing statements to have my system check if there is already an existing username before the administrator automatically creates another user with the same username.
I have been doing a little reading on PDO prepared statements for use in a dynamic web application, but as far as I have seen, no one states the proper order for a prepare statement
Are there any differences in the order of which the values and variables are parsed to the prepare statement from user input?
It would make more sense if the 'prepare' statement will have access to the user entered input (username)
Example 1
Username variables entered second. Seems like Prepare wont know what variables to
actually escape, and therefore cant protect from SQL injection
$query = $general->db->prepare('SELECT * FROM users WHERE username = :username');
$username = array('username' => $_POST['addUserName']);
$query->execute($username);
$usernames_exist = $query->fetchAll();
Example 2
Username variables entered first for proper SQL prepare
$username = array('username' => $_POST['addUserName']);
$query = $general->db->prepare('SELECT * FROM users WHERE username = :username');
$query->execute($username);
$usernames_exist = $query->fetchAll();
Can someone please clarify if there is any advantage to which order works first, in order to properly prevent SQL injection
There 2 code snippets are essentially equal in either way.
but as far as I have seen, no one states the proper order for a prepare statement
May be that's because order doesn't matter at all?
It would make more sense if the 'prepare' statement will have access to the user entered input (username)
It wouldn't. prepare() has nothing to do with user input. And even if you create just ordinal PHP array before calling prepare(), it won't become aware of the user input all of sudden.
What deals with user input is execute() /bind functions where you pass your user input. Sounds quite logical, eh?
All you need to know about SQL injection prevention is that every single variable should go into query via placeholder only. As long as you can follow this simple rule, you can consider yourself safe from injection. Any other matter, be it order of operators or number of spaces, affects nothing, as long as your code works as intended.
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do I create a PDO parameterized query with a LIKE statement in PHP?
PHP PDO prepared statement — mysql LIKE query
I'm trying to make a search engine for my website, and right now I'm just trying to make sure the connection is all and well. Here is my code thus far:
EDITED CODE (Still doesn't work, but here's where I'm at with the suggestions thus far):
$db = new PDO("mysql:host=".DB_SERVER.";dbname=".DB_NAME, DB_USER, DB_PASS);
$stmt = $db->prepare("SELECT * FROM table_1 WHERE name LIKE ? ORDER BY bid DESC");
$stmt->bindParam(1, "%{$_GET['s']}%", PDO::PARAM_STR);
$stmt->execute();
$rows = $stmt->fetchAll();
I tried to see if the different methods of execute would do anything, but regardless of which way above I write it, I get the same result, nothing. I want the % wildcard in there so it does it'll search anywhere in name. On that note, am I using it correctly? The thing that confuses me most is when I type in the exact same query into PHPMyAdmin, the query runs through fine, so my guess is that I'm screwing up the PDO somewhere.
EDIT: PHPMyAdmin Query:
SELECT *
FROM table_1
WHERE name LIKE '%Test%'
ORDER BY bid DESC
LIMIT 0 , 30
This returns 1 result, as it is expected to. What is different about my code and this query? :/
I don't really understand what your question is, but I'm guessing you don't know how to add the %? If so, try this:
$stmt = $db->prepare("SELECT * FROM table_1 WHERE name LIKE ? ORDER BY bid DESC");
$stmt->bindValue(1, "%{$_GET['s']}%", PDO::PARAM_STR);
$stmnt->execute();
// fetch and win! :-)
A little explanation:
PDO will quote and escape the parameter ? appropriately. This means, that if you are binding hello, PDO will substitute ? with 'hello' (note the quotes). Therefore, in order to have the % inside the quotes, you will have to add them to what is binded, in this case $_GET['s'].
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
What is SQL injection?
XKCD SQL injection - please explain
I own a company and am wishing to know the runabouts of PHP while I am hiring for people to maintain and extend code for its websites, I was looing up on security on SQL injections and do not quite understand how these codes can affect the SQL database as they are in contained strings to the query.
How may one show the security flaw, so that I can see for myself what is happening?
Although much of this can be explained online, I have a feeling to explain this in a bit more detail.
If you can visualise what the string will become, you will understand the underlying risks of the script you are writing, in that it will become something else before it is actually ran.
A trivial malicious example:
$fromtheuser = "foo'; DROP TABLE affiliates; --";
$q = "SELECT id FROM affiliates WHERE website = '$fromtheuser'";
Can you explain what this will become? The developer couldn't.
"SELECT id FROM affiliates WHERE website = 'foo'; DROP TABLE affiliates; --'"
The key portions of this vector being '; to end the SQL string primitive, and --' to comment out the pushed quote.
What you would be looking for in the code written, is proper sanitization and filtering of the data before it is even placed in to the query. One important tool to help secure this front is some form of prepared query, in such you can bind the parameters to the query so that there is nothing to manipulate.
We can achieve this with prepared statements in either MySQLi (improved) or my personal favourite PDO. A quick rundown of what they look like.
mysql_real_escape_string (can handle encoding and quotes)
<?php
$clean = mysql_real_escape_string($q)
MySQLi:
<?php
$clean = $mysqli->prepare("SELECT id FROM affiliates WHERE website = ?");
$clean->bind_param('s', $website); //'s' for 'string'
PDO:
<?php
$clean = $pdo->prepare("SELECT id FROM affiliates WHERE website = ?");
$clean->bindParam(1, $website); //you can use :site rather than ? and 1
mysql_query("SELECT * FROM users WHERE username = '$username'");
Look what happens when we set the $username variable to something nasty:
$username = "' OR 1";
The query becomes:
SELECT * FROM users WHERE username = '' OR 1
An attacker can use improperly escaped variables to inject SQL into your query, effectively bypassing any (poor) security measure you have in place.
More info here
It's also worth noting that there are tools through which you can test whether your site is susceptible to injection attacks.
Take a look at
http://sqlmap.sourceforge.net/
The danger coming from the fact, that SQL query being a program.
So, malicious code can be injected in place of some operator.
string being delimited by quotes. if a delimiter inside of a string weren't escaped, it will actually close string statement and the rest going to be malicious code.
not only strings being dynamic. No delimiter will protect LIMIT $amount if $amount will contain malicious code, as well as ORDER BY $order.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
PDO Prepared Statements
I'm using the mysqli extension in PHP and I'm wondering, is there possibly any way to see a prepared query as it will be executed on the server, e.g. The query is something like this
select * from table1 where id = ? and name = ?
but I want to see the query after the values are filled in, like this:
select * from table1 where id = 20 and name = "John"
Turn on mysql query logging and it will log all queries to a text file for you to review.
Duplicate of PDO Prepared Statements
Short answer: no. A prepared query will never be converted to the query you expect. It's executed directly by the database server. You can use mysql's query log or PDO's undocumented function debugDumpParams, but both are just approximations.
See it where?
If it's your code you have the query and you have the prepared parameters, log them separately or replace in the original query string.
If the binding will fail you will get an error, otherwise you should expect the same values to be "filled" in as you specified them.
Its the way most of the times I am debugging mysql quires:
$q = "select * from table1 where id = ".$id." and name = ".$name;
echo $q;
The output generates all variables assigned to the query.
Hope I understood you exactly, what you wanted.