I have search for bind parameters. But it just getting me confused. I'm really a beginner in php and mysql.
here is code:
$query ="UPDATE table_user_skills SET rating='" . $_POST["rating"] . "' where rating_id='".$_POST['id']."'";
$result = $conn->query($query);
I wonder if how can i apply the bind parameters method in this sample query. Thanks for you response.
Thanks for all the responses. My code works
update.php
$sql = "UPDATE table_user_skills SET rating=? WHERE rating_id=?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('sd', $myrate, $myrateid);
$stmt->execute();
if ($stmt->errno) {
echo "Error" . $stmt->error;
}
else print 'Your rate is accepted.';
$stmt->close();
When you write the query, leave the values (the $_POST variables) out of the SQL code and in their place use a placeholder. Depending on which interface you're using in PHP to talk to your MySQL database (there's MySQLi and PDO), you can use named or unnamed place holders in their stead.
Here's an example using PDO
$query = "UPDATE table_user_skills SET rating= :ratings where rating_id= :id";
$stmt = $conn->prepare($query);
$stmt->execute($_POST);
What we've done here is send the SQL code to MySQL (using the PDO::prepare method) to get back a PDOStatement object (denoted by $stmt in the above example). We can then send the data (your $_POST variables) to MySQL down a separate path using PDOStatement::execute. Notice how the placeholders in the SQL query are named as you expect your $_POST variables. So this way the SQL code can never be confused with data and there is no chance of SQL injection.
Please see the manuals for more detailed information on using prepared statements.
Related
I have some form data that I'm writing to a database with PDO prepared statements.
This form data is santized and validated on the on the way in to the database with filter_var() functions and regular expressions and when any of this data is outputted to the site it escaped with htmlspecialchars().
To prevent SQL injections I'm using I'm using the code below. When I first learnt PDO this was what I saw in the tutorial and I personally find it very easy to read/understand.
I've noticed on the php.net site and in some other code I've saw recently they used bindparams(), whereas in the code below I've always done this inside an array in the execute() method.
Is my code below secure? Or must I use bindparams in the way that is shown in the second code example?
Here is some sample code using a firstname input from a webform
<?php
$firstname = $_POST['firstname'];
$firstname = filter_var($fname, FILTER_SANITIZE_STRING);
if(empty(trim($fname))){
$error[] = "First Name cannot be blank";
}
$sql = "INSERT INTO users (firstname) VALUES (:firstname)";
$stmt = $connection->prepare($sql);
$stmt->execute([
':firstname' => $firstname,
]);
In the php.net docs it does the above prepared statement using bindParam(), which seems a little verbose if you are updating a number of fields?
<?php
$sql = "INSERT INTO users (firstname) VALUES (:firstname)";
$stmt = $connection->prepare($sql);
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname', $lastname);
$stmt->execute();
If it is more secure then I'll obviously have to do it the second way, but wanted to check if my prepared statements given in the first code block are secure ?
It's fine either way. The security benefit is from using placeholders at all. There are some cases (dynamically constructed queries) where it's beneficial to use bindParam separately from the execute call, and there are others where you would prefer to avoid the verbosity. Use what suits you.
Using prepared statements to query the database in PHP is making me repeat a lot of code.
For instance, if I want to fetch a particular user from the database in my users.php file, I do it like this:
$sql = "SELECT * FROM users WHERE id=?";
// prepare sql statement
$stmt = $conn->prepare($sql);
// bind query parameters
$stmt->bind_param('i', $user_id);
// execute
$stmt->execute();
// get result object
$result = $stmt->get_result();
// fetch user from result as associative array
$user = $result->fetch_assoc();
To me, this is already a lot of code just to fetch a user. But no big deal, it is more secure so it is worth it.
The problem arises when I want to insert a post into the database in my post.php file. I do it like this:
$sql = "INSERT INTO posts SET user_id=?, title=?, body=?";
$stmt = $conn->prepare($sql);
$stmt->bind_param('iss', $user_id, $title, $body);
$result = $stmt->execute();
$stmt->close();
I am already seeing code repetition here. It means in my application if I want to query the database 100 times, I will have to repeat some lines of code such as the prepare(), bind_param(), execute() steps especially since the bind_param() parameters are always changing.
I have thought of refactoring this in one or two functions say in my database.php file so that I can just call the function passing the query and the parameters and have that function do all the prepare() and bind_param() and execute() functions.
Is this possible? If so is it good practice?
Thanks for any suggestions.
I've always used PDO statements, but for some reason I can't persuade the server guy to install PDO for php, but I do have MySQLi, I have no clue what I'm doing wrong, I do not get a connection error and I do not get a query error no matter how I try to output one. Here's what I'm doing.
include 'MySQLiConnect.php';
if($stmt = $mysqli->prepare("SELECT * FROM zipCodeTable WHERE zip_code = ?")){
$stmt->bind_param("s", '07110');
$stmt->execute();
$stmt->bind_result($resultsArray);
$stmt->fetch();
foreach($resultsArray as $columnData){
$matchingZipcode = $columnData['zip_code'];
$matchingTimezone = $columnData['time_zone'];
}
$stmt->close();
}
echo $matchingZipcode.', '.$matchingTimezone;
This is basically just to confirm a users zipcode, never used MySQLi prepared statements before, I tryed to do it straight from the manual, not sure what I'm doing wrong. Thank you for taking the time to read this.
You're trying to "bind" a literal string. You can't do this. You must bind a variable.
Change
$stmt->bind_param("s", '07110');
To
$string = '07110';
$stmt->bind_param("s", $string);
Also, when you bind a result you must provide a variable for each field returned.
For example:
$stmt->bind_result($zipCode, $timeZone);
This is slightly problematic when using SELECT *. You might be interested in checking out this comment for how you might want to go about it: http://www.php.net/manual/en/mysqli-stmt.bind-result.php#85470
I am starting a very basic site that uses a single line form to post into a database and then later echo that $comment variable on the page. I don't know PDO, but am willing to learn if I truly need it for something this simple.
else
mysql_query("INSERT INTO posts (postid, post_content)
VALUES ('', '$comment <br />')");
}
mysql_close($con);
Above this code I have basic strpos commands to block out some of the things I don't want posted.
Am I going to experience any issues with injections down the road from how I am doing this?
No, it's not safe, you need to use mysql_real_escape_string to escape $comment.
But, PDO is nothing difficult and make your code stronger.
// create the connection. something like mysql_connect/mysql_error
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
// create the prepared statement.
$stmt = $dbh->prepare("INSERT INTO posts (postid, post_content) VALUES (?, ?)");
// execute it with parameters.
$stmt->execute(array('', $comment.'<br>'));
Yes this is dangerous. All someone has to do is put a single quote then the SQL code they want after. Use $comment = mysql_real_escape_string($comment) before this statement if you want to fix it the old way or use PDO prepared statements as the newer way. Here is a basic example from the documentation:
<?php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
// insert one row
$name = 'one';
$value = 1;
$stmt->execute();
// insert another row with different values
$name = 'two';
$value = 2;
$stmt->execute();
?>
This is susceptible to sql injection as your $comment is input from the user they may as well enter some SQL command and your PHP code will end up executing the same.
Consider $comment value is set to 'TRUNCATE TABLE USERS;' the USERS table could be anything which might be critical for your app.
In PHP I believe you safeguard against sql injection by using mysql_real_escape_string(). Read up on it.
Refer this doc for details abt SQL innjection: https://docs.google.com/document/d/1rO_LCBKJY0puvRhPhAfTD2iNVPfR4e9KiKDpDE2enMI/edit?pli=1
Binding form input data to mysql query is the perfect solution to the sql injection. Use binaParam method for this purpose.
No, judging only by the code you’ve posted here, you are not protected against SQL injections. Here’s a simple example for $comment:
'), (null, (select concat(user(),':',password) s from mysql.user where concat(user,'#',host)=user() LIMIT 1) --
This will add another row containing the login credentials of the current user. With LOAD_FILE he could also be able to read files from your file system. He could also write arbitrary files on the file system:
' + (select '<?php echo "Hello, World!";' into dumpfile '/path/to/your/document_root/foobar.php')) --
With this technique the attacker could upload arbitrary files to your server, e. g. a web shell to run arbitrary commands on your system.
So you definitely must protect yourself against SQL injections whereby automatic escaping using prepared statements or parameterized statements is favored over manual escaping using functions like mysql_real_escape_string.
I'm working on learning to use prepared statements with mysqli in PHP and usually, if I'm having a problem with a query I just echo it to the screen to see what it looks like as a first step.
How can I do that with a prepared statement?
I'd like to see the SQL statement after the variables are substituted.
Using prepared statements:
When you prepare the statement, it is sent to the MySQL server
When you bind the variables + execute the statement, only the variables are sent to the MySQL server
And the statement + bound variables are executed on the MySQL server -- without it re-doing the "preparation" each time the statement is executed (which is why prepared statements can be good for performance when the same statement is executed several times)
There is no "building" of an SQL query on the PHP side, so, there is no way to actually get that query.
Which means that if you want to see an SQL query, you have to use, well, SQL queries, and not prepared statements.
You can use PDOStatement->debugDumpParams to get some informations about the prepared statement (in case you're using pdo).
Prepared statements are logged in MySQL's general log:
For prepared statements that are executed with the mysql_stmt_prepare() and mysql_stmt_execute() C API functions, the server writes Prepare and Execute lines to the general query log so that you can tell when statements are prepared and executed.
[...] the server writes the following lines to the general query log:
Prepare [1] SELECT ?
Execute [1] SELECT 3
So for debugging purposes active the general log and keep an eye on that file.
edit: oh, the question has a [mysqli] tag... completely overlooked that.
If the statement isn't executed at all have you (double/tripple) checked that no error occurred along the way?
echo "<pre>Debug: start</pre>\n";
$mysqli = new mysqli('localhost', 'localonly', 'localonly', 'test');
if ($mysqli->connect_error) {
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}
$result = $mysqli->query('CREATE TEMPORARY TABLE foo (id int auto_increment, x int, primary key(id))');
if ( false=== $result) {
die('error : '. $mysqli->error);
}
$stmt = $mysqli->prepare('INSERT INTO foo (x) VALUES (?)');
if ( false===$stmt ) {
die ('prepare() failed: ' . $mysqli->error);
}
$result = $stmt->bind_param('i', $x);
if ( false===$result ) {
die('bind_param() failed');
}
$x = 1;
$result = $stmt->execute();
if ( false===$result ) {
die('execute() failed: '.$stmt->error);
}
echo "<pre>Debug: end</pre>\n";
I usually do this when I need to debug a prepared sql with parameters.
Example of prepare and execute:
$sql = "SELECT VAL1, VAL2 FROM TABLE(?, '?', '?', '?', '?', ?, '?', '?', '?')";
$prep = ibase_prepare( $sql ) or die("Error");
$query = ibase_execute($prep, $param1, $param2, .....) or $err = true;
^^^^^^^^^^^^^^^^^^^^^^^
The easy way to debug the resulting SQL of the sentence it's:
printf( str_replace('?', '%s', $sql), $param1, $param2, ....);
^^^^^^^^^^^^^^^^^^^^^^
You only need to do one printf, replacing the ? on the prepared SQL string by one %s. printf will interpret all as one string, taking each parameter as placing it on each replaced %s.
I recently updated this project to include composer integration, unit testing and to better handle accepting arguments by reference (this requires updating to php 5.6).
I've created a set of classes that extend the default mysqli and mysqli_stmt classes to allow you to view a rendition of the potential query string, which should provide what you're looking for:
https://github.com/noahheck/E_mysqli
This is a (close to) drop-in replacement for you normal mysqli object that returns a custom mysqli_stmt object when you prepare() the query string. After binding your parameters, E_mysqli will allow you to view the resultant query string as a new property of the stmt object:
$mysqli = new E_mysqli($dbHost, $dbUser, $dbPass, $dbName);
$query = "INSERT INTO registration SET name = ?, email = ?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $_POST['name'], $_POST['email']);
$stmt->execute();
echo $stmt->fullQuery;
would result in:
INSERT INTO registration SET name = 'John Doe', email = 'john.doe#example.com'
There are some caveats with using this extension (explained in the README at the github project), but for troubleshooting troublesome areas of your application, or transitioning to an object oriented style from procedural, this should provide a level of help for most users.
As I've outlined in the github project, I don't have any practical experience using the mysqli extension, and this project was created at the request of users of it's sister project, so any feedback that can be provided from devs using this in production would be greatly appreciated.
Disclaimer - As I said, I made this extension.
Agreeing with Pascal MARTIN (+1) so I suggest another technique for debugging: var_dump() or log every variable you're inserting into the statement, that way you should be able to figure out if it is wrong data or logically wrong SQL.
You can use tool like Lottip. The idea is act like MySQL proxy. It parses MySQL packets, extracts query and it's params so you can see prepared statements with it's content.