I understand that mysqli_real_escape_string() function is used to prevent SQL injection, but I don't know why this function is designed to take two parameters instead of only one? I understand $_POST["firstname"] is the input String to get escaped using this function but why the $connection is also needed as the first parameter? I am a starting php learner, sorry if this question doesn't make too much sense.
// escape variables for security
$firstname = mysqli_real_escape_string($con, $_POST['firstname']);
var_dump($firstname);
$lastname = mysqli_real_escape_string($con, $_POST['lastname']);
$age = mysqli_real_escape_string($con, $_POST['age']);
$sql="INSERT INTO Persons (FirstName, LastName, Age)
VALUES ('$firstname', '$lastname', '$age')";
if (!mysqli_query($con,$sql)) {
die('Error: ' . mysqli_error($con));
}
echo "1 record added";
mysqli_close($con);
?>
As shown in the PHP manual:
The procedural style for this function requires a mysqli instance, in other words, a connection to the database previously created (This may be oversimplifying):
string mysqli_real_escape_string ( mysqli $link , string $escapestr )
In order to call this function without the first parameter you need to instanciate the mysqli class, hence providing the function with the connection without really adding any other parameter. This is how the class is instanciated:
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");
And this would be the way to call the function in an object oriented manner:
$string = $mysqli->real_escape_string($string);
Hope this clarifies a bit your question.
Related
I'm trying to convert some php code that uses mysql into mysqli code. I'm not sure why it doesn't work - I didn't write the original code and am not that comfortable with the hash part of it, and it seems to be where the issue is. As I show in the code below, the "error" part gets echo'ed so it's something to do with the hash strings, but I don't really understand why changing to mysqli has broken the code. Both versions of the code are below, and the original code works. I deleted the variables (host name, etc.) but otherwise this is the code I am working with.
Mysql Code:
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
$db_link = mysql_connect($host_name, $user_name, $password) //attempt to connect to the database
or die("Could not connect to $host_name" . mysql_connect_error());
mysql_select_db($db_name) //attempt to select the database
or die("Could not select database $db_name");
return $db_link;
}
$db_link = db_connect(""); //connect to the database using db_connect function
// Strings must be escaped to prevent SQL injection attack.
$name = mysql_real_escape_string($_GET['name'], $db_link);
$score = mysql_real_escape_string($_GET['score'], $db_link);
$hash = $_GET['hash'];
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $hash) {
// Send variables for the MySQL database class.
$query = "insert into scores values (NULL, '$name', '$score');";
$result = mysql_query($query) or die('Query failed: ' . mysql_error());
}
Mysqli code (doesn't work):
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
$db_link = mysqli_connect($host_name, $user_name, $password) //attempt to connect to the database
or die("Could not connect to $host_name" . mysqli_connect_error());
mysqli_select_db($db_link, $db_name) //attempt to select the database
or die("Could not select database $db_name");
return $db_link;
}
$db_link = db_connect(""); //connect to the database using db_connect function
// Strings must be escaped to prevent SQL injection attack.
$name = mysqli_real_escape_string($_GET['name'], $db_link);
$score = mysqli_real_escape_string($_GET['score'], $db_link);
$hash = $_GET['hash'];
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $hash) {
// Send variables for the MySQL database class.
$query = "INSERT INTO `scores` VALUES (NULL, '$name', '$score');";
$result = mysqli_query($db_link, $query) or die('Query failed: ' . mysqli_error($db_link));
echo $result;
}
else {
echo "error"; //added for testing. This part gets echoed.
}
mysqli_close($db_link); //close the database connection
One notable "gotchu" is that the argument order is not the same between mysql_real_escape_string and mysqli_real_escape_string, so you need to swap those arguments in your conversion.
$name = mysqli_real_escape_string($db_link, $_GET['name']);
$score = mysqli_real_escape_string($db_link, $_GET['score']);
It's good that you're taking the time to convert, though do convert fully to the object-oriented interface if mysqli is what you want to use:
// Send variables for the MySQL database class.
function db_connect($db_name)
{
$host_name = "";
$user_name = "";
$password = "";
// Enable exceptions
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$db = new mysqli($host_name, $user_name, $password);
$db->select_db($db_name);
return $db;
}
$db = db_connect(""); //connect to the database using db_connect function
$secretKey=""; # Change this value to match the value stored in the client javascript below
$real_hash = md5($name . $score . $secretKey);
if($real_hash == $_GET['hash']) {
// Don't include ; inside queries run through PHP, that's only
// necessary when using interactive MySQL shells.
// Specify the columns you're inserting into, don't leave them ambiguous
// ALWAYS use prepared statements with placeholder values
$stmt = $db->prepare("INSERT INTO `scores` (name, score) VALUES (?, ?)");
$stmt->bind_param("ss", $_GET['name'], $_GET['score']);
$result = $stmt->execute();
echo $result;
}
else {
echo "error"; //added for testing. This part gets echoed.
}
// Should use a connection pool here
$db->close();
The key here is to use prepared statements with placeholder values and to always specify which columns you're actually inserting into. You don't want a minor schema change to completely break your code.
The first step to solving a complex problem is to eliminate all of the mess from the solution so the mistakes become more obvious.
The last if statement is controlling whether the mysql query gets run or not. Since you say this script is echoing "error" form the else portion of that statement, it looks like the hashes don't match.
The $hash variable is getting passed in on the URL string in $_GET['hash']. I suggest echo'ing $_GET['hash'] and $real_hash (after its computed by the call to MD5) and verify that they're not identical strings.
My hunch is that the $secretKey value doesn't match the key that's being used to generate the hash that's passed in in $_GET['hash']. As the comment there hints at, the $secretKey value has to match the value that's used in the Javascript, or the hashes won't match.
Also, you may find that there's a difference in Javascript's md5 implementation compared to PHP's. They may be encoding the same input but are returning slightly different hashes.
Edit: It could also be a character encoding difference between Javascript and PHP, so the input strings are seen as different (thus generating different hashes). See: identical md5 for JS and PHP and Generate the same MD5 using javascript and PHP.
You're also using the values of $name and $score after they've been escaped though mysqli_real_string_escape, so I'd suggest making sure Javascript portion is handling that escaping as well (so the input strings match) and that the msqli escape function is still behaving identically to the previous version. I'd suggest echo'ing the values of $name and $score and make sure they match what the Javascript side is using too. If you're running the newer code on a different server, you may need to set the character set to match the old server. See the "default character set" warning at http://php.net/manual/en/mysqli.real-escape-string.php.
I'm trying to make my first registration script using PHP/SQL. Part of my code isn't working:
if(!$errors){
$query = "INSERT INTO users (email, password) VALUES ($registerEmail, $registerPassword)";
if(mysqli_query($dbSelected, $query)){
$success['register'] = 'Successfully registered.';
}else{
$errors['register'] = 'Registration did not succeed.';
}
}
When I test my code I get the error 'Registration did not succeed.' For reference, $errors and $success are arrays. Is there anything wrong with this part of my script?
$dbSelected is:
$dbLink = mysqli_connect('localhost', 'root', 'PASSWORD');
if (!$dbLink) {
die('Can\'t connect to the database: ' . \mysqli_error());
}
$dbSelected = mysqli_select_db($dbLink, 'devDatabase');
if (!$dbSelected) {
die('Connected database, but cannot select
devDatabase: ' . \mysqli_error());
}
I'm sure I am connecting and selecting the database.
Any help would be greatly appreciated! I am very new to PHP/SQL so forgive me for any noob mistakes.
Quote the string like below
$query = "INSERT INTO users (email, password) VALUES ('$registerEmail', '$registerPassword')";
You can also do
echo $query;
and take the output on the browser, copy and paste into PHPMyAdmin and execute it from there. It should tell you what is wrong with the query.
I suggest you to use prepared statement as using string concatenation in SQL Statement is prone to SQL injection attack. Refer the example PHP mysqli prepare
First off, PHP is deprecating mysql_ functions, you should migrate to PDO instead.
Also, make sure since you're using the older mysql_ functions to sanitize your entries using mysql_real_escape_string
Also, your entries need to be quoted. Here's a redo of your query string:
$query = "INSERT INTO users (email, password) VALUES ('{$registerEmail}', '{$registerPassword}')";
How would I go about writing a SQL statement that would insert values that might contain an apostrophe (for example one person's last name was Conner and another's was O'Conner)? After some searching, I found examples using a double apostrophe (O''Conner example) but each example had the string hard coded in the the INSERT. I haven't run across any examples where the value may or may not contain an apostrophe.
My simple statement doesn't have any issues when no apostrophe is used but when one is it fails. I know I could replace the apostrophe using str_replace but, obviously, that would cause the O'Conner example to be displayed as OConner.
Here is a shorthand version, just for an example:
page1.php
// PHP
include_once('phpdata.php');
if (isset($_POST['firstname']) && isset($_POST['lastname'])) {
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
// SQL connection
$insert = doInsert($firstname, $lastname);
// Execute statement using odbc_exec, etc.
}
// HTML
<input type="text" class="required" name="firstname" id="firstname" />
<input type="text" class="required" name="lastname" id="lastname" />
phpdata.php
function doInsert($firstname, $lastname) {
$insert = "INSERT INTO mytable (firstname, lastname)
VALUES ('$firstname', '$lastname')";
return $insert;
}
Using PDO with prepared statements will take care of escaping your inputs :
$dsn = "mysql:host=localhost;dbname=your_db_name";
try {
$db = new PDO($dsn, 'your_username', 'your_pass');
} catch (PDOException $e) {
die( "Erreur ! : " . $e->getMessage() );
}
$query = "INSERT INTO mytable (firstname, lastname)
VALUES (:firstname', :lastname)";
$stmt = $db->prepare($query);
$stmt->bindParam(':firstname', $firstname);
$stmt->bindParam(':lastname', $lastname);
$stmt->execute();
Doc : PHP Data Objects
You could use replace to replace all ' with ''. However, the proper way to do it is use parameterized queries where you pass your value to insert to the SQL Statement as a parameter. Then the language can clean up ' and any other characters/keywords that could cause an issue. No matter the language, parameterized queries are the way to go.
Consider using prepared statements. It's the best way to input user submitted data into a database. It makes sure the data is properly escaped automatically!
phpdata.php
<?php
function doInsert($firstname, $lastname) {
$insert = "INSERT INTO mytable (firstname, lastname)
VALUES (?, ?)";
$pstmt = odbc_prepare($odb_con, $insert); /* Use global $odb_con to access the connection */
$res = odbc_execute($pstmt, array($firstname, $lastname));
return $res; /* Should return TRUE on success. */
}
?>
Do note that I haven't included any error checking in my code. Might be wise to implement that as well.
Good luck!
You can try use function addslashes for prepare data before insert.
I don't know how your work with database but this function is simple way for ask to your question.
AddSlashes
So, I have a form that posts to my php file using ajax, and succeeds. But the following query doesn't insert anything. Can someone help me understand what I'm doing wrong?
My php file:
<?php
include 'connect.php' ;
$type = mysql_real_escape_string($_POST['type']);
$title = mysql_real_escape_string($_POST['title']);
$content = mysql_real_escape_string($_POST['content']);
if ($type == 'Just Text') {
mysql_query("INSERT INTO articles (title, type, thisisaninteger, content) VALUES ('".$title."', '".$type."', 0, '".$content."')")or die("MySQL Error: " . mysql_error());
}
?>
My connect.php:
<?php
$dbhost = "localhost";
$dbname = "example";
$dbuser = "test";
$dbpass = "test";
mysql_connect($dbhost, $dbuser, $dbpass) or die("MySQL Error: " . mysql_error());
mysql_select_db($dbname) or die("MySQL Error: " . mysql_error());
?>
If you aren't receiving any errors and the INSERT just doesn't happen, it is most likely because the if statement fails to be true. Verify that $type actually matches Just Text.
You should also be inserting values using prepared statements, and use PDO or MySQLi - this article will help you decide which.
first, echo "something" after the if statement and recall the data with your ajax post. you can find out if your if statement is working, then try formatting your variables like so
mysql_query("INSERT INTO articles (title, type, thisisaninteger, content) VALUES ('$title', '$type', 0, '$content')")or die("MySQL Error: " . mysql_error());
I just want to throw in an official vote/recommendation in favor of switching to a parameterized SQL statement, too. In spite of the use of mysql_real_escape_string, schlepping a SQL statement together via string concatenation is neither necessary nor a good idea. Honestly, I find a prepared statement much, much easier to read than the typical string-concatenation exercise, as well:
$stmt = $dbh->prepare("SELECT * FROM users WHERE USERNAME = ? AND PASSWORD = ?");
$stmt->execute(array($username, $password));
Alright, it was a stupid mistake on my side. There were columns I didn't include and they were not being assigned a value. Thanks everyone for helping out.
Im using the follow script to insert records into my DB:
$sql = "INSERT INTO fotetweets VALUES('$tweetid','$dp', '', '$username','$tag', '$twittercontent', '$twittertimestamp', '')";
mysql_query($sql);
However what if $twittercontent contains the ' char, I think it will fail. Correct?
If so how can I deal with it correctly?
You will want to look into mysql_real_escape_string. However, I would look into using the mysqli or PDO class instead and utilize prepared statements.
EDIT
Note, these can all be found / were pretty much taken from the PHP Manual under examples for prepared statements.
Example Usage for MySQLi:
<?php
$mysqli = new mysqli("localhost", "my_user", "my_password", "my_database");
/* check connection */
if (mysqli_connect_errno()) {
printf("Connect failed: %s\n", mysqli_connect_error());
exit();
}
/* create a prepared statement */
$stmt = $mysqli->stmt_init();
if ($stmt->prepare("INSERT INTO fotetweets VALUES(?, ?, '', ?, ?, ?, ?, '')")) {
/* bind parameters for markers */
$stmt->bind_param("issssi", $tweetid, $dp, $username, $tag, $twittercontent, $twittertimestamp);
/* execute query */
$stmt->execute();
/* close statement */
$stmt->close();
}
?>
Example Usage PDO:
<?php
$dsn = 'mysql:dbname=testdb;host=127.0.0.1';
$user = 'dbuser';
$password = 'dbpass';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$sth = $dbh->prepare('INSERT INTO fotetweets VALUES(?, ?, '', ?, ?, ?, ?, '')');
$sth->execute(array($tweetid, $dp, $username, $tag, $twittercontent, $twittertimestamp));
?>
Example of mysql_real_escape_string usage:
$tweetid = (int) $tweetid; // static cast to integer, if that is what it should be.
$sql = "INSERT INTO fotetweets VALUES(
$tweetid,'" . mysql_real_escape_string($dp) . "',
'', '" . mysql_real_escape_string($username) . "',
'" . mysql_real_escape_string($tag) . "',
'" . mysql_real_escape_string($twittercontent) . "',
'" . mysql_real_escape_string($twittertimestamp) . "', '')";
You can find more information and extra usage examples at the manual pages listed above. Given I do know what $dp is I cannot tailor this exactly.
SIDE NOTE
This is all the assumption I am willing to make. The OP could be getting the data from POST and/or in an array form, or he could be getting it from a different means. Either or, given the example the OP posted, this is as accurate as I could be to tailor to the OP. If you have an issue or think it could be better explained / shown, well go ahead and add another answer which addresses it and not just another complaining comment remark about how no one does anything right when you are not willing to pony up the "correct" answer yourself.
And of course if it is an array, this changes a lot of items and the OP should clear that up and not just random people making "guesses" as to where and how the data is being retrieved.
Correct. Not only it will fail but it will also leave you open to SQL Injection attacks.
To avoid these problems, you can use:
mysql_real_escape_string()
PDO and Prepared Statements
Remember, user input should always be sanitized.
Just before you run this query, use this:
$twittercontent = mysql_real_escape_string($twittercontent);
yes it would fail as it would prematurely terminate the string. To fix this use
mysql_real_escape_string($twittercontent) in place of $twittercontent
Make your life simpler:
//$pdo = new PDO("mysql:host=localhost;dbname=testdb", user, pass);
$pdo->prepare("INSERT INTO fotetweets VALUES (?,?,?,?,?,?,?,?)")
->execute( array($tweetid, $dp, '', $username, $tag, $twittercontent, $twittertimestamp, '') );
This sends the data correctly to the database, without security issues. Use it as template for all queries. (Note that you still have to apply htmlspecialchars() when outputting your database content again later...)
That's why you should use mysql_real_escape_string() function first
http://www.php.net/manual/en/function.mysql-real-escape-string.php
It is important, that you always escape (or in general sanitize) variables you interpolate into your queries that come from untrusted sources (i.e. not from you ;) ). Topic for you to Google for read about: 'SQL injection'
You can also use addslashes(). mysql_real_escape_string() is better though. I agree with using PDO.
As it was mentioned before me you can use mysql_real_escape_string
OR
if you use PDO you can also use binding and the you do not have to worry about escaping.
$stmt = $db->prepare("INSERT INTO fotetweets VALUES(:tweetid,:dp, '', :username,:tag, :twittercontent, :twittertimestamp, '')");
$stmt->bindParam(':tweetid', $tweetid);
$stmt->bindParam(':dp', $dp);
$stmt->bindParam(':username', $username);
$stmt->bindParam(':tag', $tag);
$stmt->bindParam(':twittercontent', $twittercontent);
$stmt->bindParam(':twittertimestamp', $twittertimestamp);
$stmt->execute();
As it was mentioned above, you have to use mysql_real_escape_string()
note that you have to use this function not for the $twittercontent variable only,
but for the every field in the query
and not only for inserting and not only for this table.
and from "untrusted input".
But literally every variable you are going to put into query in quotes, should be processed with this function. No exceptions or conditions.
Note if you don't put variable in quotes in the query, this function become useless
Another way, already mentioned too, is to change entire database driver.
Unfortunately, noone bring a useful example of real life usage, which could be extremely useful.