Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
$stmt_update = $db->prepare("UPDATE 2_1_journal SET RecordDay = ?, WHERE Number = ? ");
$stmt->execute(array($amount1, $date_day1));
Is this safe against mysql injections?
If safe, as I understand it is because of "= ?". Then question how "= ?" works/helps
Question is because here http://php.net/manual/en/pdo.prepare.php is written
Prepared statements only project you from SQL injection IF you use the bindParam or bindValue option.
For example if you have a table called users with two fields, username and email and someone updates their username you might run
UPDATE `users` SET `user`='$var'
where $var would be the user submitted text.
Now if you did
<?php
$a=new PDO("mysql:host=localhost;dbname=database;","root","");
$b=$a->prepare("UPDATE `users` SET user='$var'");
$b->execute();
?>
and the user had entered User', email='test for a test the injection would occur and the email would be updated to test as well as the user being updated to User.
In my code (above) there is no bindParams and no bindValue. So do not know if it is safe and if yes, then what part of code ensures it. Please, advice
Update
After reading this How can I prevent SQL injection in PHP? have got one more question
Does this code
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->execute(array($name));
the same as this?
$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
$stmt->execute(array(':name' => $name));
If yes, then seems it is better to use first code because it is shorter?
Yes, prepared statements are always safe from inject attacks as long as there are no logical flaws, such as using name = '?'.
bindParam is really helpful when you want to bind different datatypes; such as string, integer etc in the query. For eg:
$stmt = $pdo->prepare('SELECT * FROM employees WHERE myID = ?');
$stmt->bindParam( 1, $id, PDO::PARAM_INT );
$stmt->execute();
Prepared statements only project you from SQL injection IF you use the bindParam or bindValue option.
Manual is incorrect here. Passing data into execute() is safe as well. The main thing is using a placeholder to represent the actual data in the query. As long as you're using a placeholder instead of the actual data - you are safe. However, PDO doesn't offer you placeholders for the everything you can add into query, identifiers for example.
Does this code the same as this?
Yes.
Named placeholders are just a "syntax sugar" for a regular ones.
Technically they are the same in either way - so, it's only a matter of taste.
Personally I prefer regular question mark placeholders as they indeed makes the code dramatically shorter, while named placeholders makes it bloated with no benefit.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am creating a form that will be submitted by the user. In the form submission process, some values are hardcoded in the source code and are inserted as it is. Can I pass these values directly to the prepared statement? Other user input data I am binding that will be replaced with the ? placeholder.
For example:
...
$litVariable = 1;
$userInput = $_POST['user_input'];
$myquery = $mysqli->prepare("INSERT INTO table(`column1`,`column2`) VALUES('$litVariable',?)");
$myquery->bind_param("s",$user_input);
...
Is that ok and safe to pass $litVariable directly to query and user-generated input with $myquery->bind_param("s",$user_input);, as I did above?
Yes, what you are doing should be safe, because the value $litVariable which you are concatenating into the query string does not come from the outside. This means that the first item in your VALUES clause should not be prone to injection attacks coming from the outside. That being said, I would still suggest not even doing this, because it leaves your insert query looking prone to attack. There is no reason to not use bound parameters everywhere. That is, I suggest the following:
$litVariable = 1;
$userInput = $_POST['user_input'];
$sql = "INSERT INTO table(column1, column2) VALUES (?, ?)";
$myquery = $mysqli->prepare(sql)
$myquery->bind_param("is", $litVariable, $user_input);
This question is more about psychology than technology.
When your processing is uniform, you don't have to measure every single variable you are working with, considering whether it is secure or not. You will get in return
faster coding. you don't have to stop and think, how this particular variable is going to be inserted - as is or prepared. For the every single variable.
no chance for the human error when you can swear that a variable is safe but in reality it is not
To soften the pill, I can offer you a mysqli helper function that can make your prepared queries less boring
$sql = "INSERT INTO table(column1, column2) VALUES (?, ?)";
prepared_query($mysqli, $sql, [$litVariable, $userInput]);
only two lines of meaningful code versus four lines of repetitive code.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
How do I get html form POST data to appear after the = signs?
$tsql = "UPDATE dbo.[order]
SET status=''
WHERE order_ID='' ";
All POST data is stored in $_POST
put $_POST['dataname'] there.
SET status='".$_POST['dataname']."'
would be the proper replacement.
POST data can be retrieved using the $_POST suberglobal like this:
.... " SET status = '{$_POST['form_field_name']}'";
HOWEVER, I would recommend using prepared statements for this whenever possible. Putting form data directly into an SQL statement is a bad practice and can cause security issues.
You should use a prepared statement like this:
// Store the form data in variables
$status = $_POST['status_field'];
$order_ID = $_POST['order_ID_field'];
// If you're not going to use prepared statements AT LEAST do this
// Not a necessary step if using prepared statements
$sanitized_status = mysqli_real_escape_string($dbConnection, $status);
$sanitized_order_ID = mysqli_real_escape_string($dbConnection, $order_ID);
// Prepare the SQL
// When script is run database will compile this statement first
$stmt = $dbConnection->prepare('UPDATE table_name SET status = ? WHERE order_ID = ?');
// Parameters are bound to the COMPILED statement not the string
$stmt->bind_param('si', $sanitized_status, $sanitized_order_ID);
$stmt->execute();
The key is to bind your form data to the compiled statement and not the SQL string itself. Read more about prepared statements in this excellent resource below!
Reference: How can I prevent SQL injection in PHP?
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.
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.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm trying to confirm a users email where the users verification key is the variable $verify_mod. However, I get the error,
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE verification='72b4ad7ee82dd6e177f2588c168abb51user=test123'' at line 1
Here's my query:
$confirm_query = "INSERT INTO users (confirm_email) VALUES ('1') WHERE verification='$verify_mod'";
The INSERT statement doesn't go with a WHERE clause. Either you're trying to insert something, in which case you should remove the WHERE clause, or you want to modify a value, in which case you should use UPDATE .. SET.
// For an insert:
$confirm_query = "INSERT INTO users (confirm_email) VALUES ('1')";
// For an update:
$confirm_query = "UPDATE users SET confirm_email='1' WHERE verification='$verify_mod'";
Besides that, it's always a good idea to put ` characters around table and column names to reduce the risk of SQL injection. So:
// For an insert:
$confirm_query = "INSERT INTO `users` (`confirm_email`) VALUES ('1')";
// For an update:
$confirm_query = "UPDATE `users` SET `confirm_email`='1' WHERE `verification`='$verify_mod'";
Lastly, I don't know if you're using mysqli_* functions or PDO or mysql_* functions (in the latter case you should definitely change to one of the others as mysql_* is deprecated). In any of the first two cases you should use parameterized queries or prepared statements. You prepare the query and then fill in the variables ($verify_mod here). That way, the variables get escaped properly, again, to reduce the risk of SQL injection.
You are doing an insert, this sounds like it should be an update statement though (you can't do where in inserts either as it doesn't make sense to):
$confirm_query = "UPDATE users set confirm_email=1 WHERE verification='$verify_mod'"
Extending upon #CamilStaps answer, here's how you can parameterize your query using mysqli.
// For an insert: (No need to bind parameters for this one)
$confirm_query = $mysqli->prepare("INSERT INTO `users` (`confirm_email`) VALUES ('1')");
$confirm_query->execute();
// For an update:
$confirm_query = $mysqli->prepare("UPDATE `users` SET `confirm_email`='1' WHERE `verification`= ? ");
$confirm_query->bind_param('s', $verify_mod);
$confirm_query->execute();