Is mysqli_real_escape_string safe? - php

I´m new in PHP and I´ve realised that my database connection, using a php form (with user and pass text inputs) was totally unsafe:
This was working, but was unsafe:
<?php
$link=mysqli_connect('localhost','xx','xx','xx');
$sql=' SELECT * FROM usuarios
WHERE username="'.$_POST['usuario'].'"
AND pass="'.$_POST['usuario'].'"
';
$rs=mysqli_query($link,$sql);
mysqli_close($link);
?>
So, I´ve read about mysqli_real_escape_string, and decided to try it out:
<?php
$link=mysqli_connect('localhost','xx','xx','xx');
$usuario=mysqli_real_escape_string($link, $_POST["usuario"]);
$clave=mysqli_real_escape_string($link, $_POST["clave"]);
$sql=' SELECT * FROM usuarios
WHERE username="'.$usuario.'"
AND pass="'.$clave.'"
';
$rs=mysqli_query($link,$sql);
mysqli_close($link);
?>
Is this correct? Is this a good example of how to use mysqli_real_escape_string?

Is this correct?
Yes. This isolated handpicked example is safe. It doesn't mean, though, that mysqli_real_escape_string should be viewed as a function that's purpose is to prevent SQL injections. Because in this example it protects you only by accident.
Is this a good example of how to use mysqli_real_escape_string?
Not at all
This function should be abandoned in favor of using parameters in the query. This function will fail you with any query part other than a string literal. And can be even simply overlooked.
A placeholder, also called a parameter, have to be used instead, to represent the data in your query:
$sql='SELECT * FROM usuarios WHERE username=?';
$stmt= $conn->prepare($sql);
$stmt->bind_param("s", $_POST['usuario']);
$stmt->execute();
$rs = $stmt->get_result();
See other examples in my article on the correct use of mysqli
If ever used, this function MUST be encapsulated into another function that does both escaping AND adding quotes, just like PDO::quote() does. Only this way it will be safe.

The use of mysqli() functions should only be reserved for framework developers and others who are aware of all the safety issues it can bring. For everyone else, there's PDO. It's just as easy to use as mysqli(), and far safer.

Yes you will use it save now.
The nice thing about using mysqli is that it is Object oriented.
So you can use it like this:
<?php
$mysqli = new mysqli("host", "user", "password", "database");
$usuario = $mysqli->real_escape_string($_POST["usuario"]);
$clave = $mysqli->real_escape_string($_POST["clave"]);
$sql=' SELECT * FROM usuarios
WHERE username="'.$usuario.'"
AND pass="'.$clave.'"
';
$mysqli->query($sql);
$mysqli->close();
?>
Or you can use PDO.

Related

mysql_real_escape_string conversion to mysqli

Ok I would like to know how you convert this mysql code into mysqli.
function protect($string) {
return mysql_real_escape_string(strip_tags(addslashes($string)));
}
I know you change mysql to mysqli but it asks for 2 parameters this worked with mysql so I would like to see it in mysqli
also I haven't yet found someone on stackoverflow with a question about the new mysqli version so I wasn't able to find out myself
It is better not to use it at all!
mysql_real_escape_string() was a hack which was used to prevent SQL injection, and it didn't even do that 100%. This function was never meant to protect anything. It is a simple string formatting function.
mysqli_real_escape_string() is yet another hack to make the transition easier. Although, at the time of writing this post mysql_* has been deprecated for so long, that no one should have any excuse to use some kind of shim for transitioning, because everyone should already be using MySQLi with prepared statements or even better PDO.
As for strip_tags() and addslashes() they are useless in this context and only mutilate your data. Don't use them.
To protect against SQL injection, one should use prepared statements and ensure that no variable input is inserted into SQL directly.
For example:
$stmt = $mysqli->prepare('SELECT columnA FROM tableB WHERE columnC=?');
$stmt->bind_param('s', $someVariable);
$stmt->execute();
$result = $stmt->get_result();
This function is a bad idea.
Using strip_tags() and addslashes() indiscriminately on all incoming data needlessly mutilates it, with zero added security.
To feed data into the database, use only the string escaping function, real_escape_string().
To display data from the user on a HTML page, strip the tags then or use htmlspecialchars() to avoid any scripting attacks.
Try like this:
$mysqli = new mysqli("host", "username", "pword", "db");
function protect($string) {
return $mysqli->real_escape_string(strip_tags(addslashes($string)));
}
EDIT
$link = mysqli_connect("localhost", "root", "", "aaa");
$city = "'s Hertogenbosch";
$city = mysqli_real_escape_string($link, $city);
echo($city);

What is the PDO equivalent of function mysql_real_escape_string?

I am modifying my code from using mysql_* to PDO. In my code I had mysql_real_escape_string(). What is the equivalent of this in PDO?
Well No, there is none!
Technically there is PDO::quote() but it is rarely ever used and is not the equivalent of mysql_real_escape_string()
That's right! If you are already using PDO the proper way as documented using prepared statements, then it will protect you from MySQL injection.
# Example:
Below is an example of a safe database query using prepared statements (pdo)
try {
// first connect to database with the PDO object.
$db = new \PDO("mysql:host=localhost;dbname=xxx;charset=utf8", "xxx", "xxx", [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
} catch(\PDOException $e){
// if connection fails, show PDO error.
echo "Error connecting to mysql: " . $e->getMessage();
}
And, now assuming the connection is established, you can execute your query like this.
if($_POST && isset($_POST['color'])){
// preparing a statement
$stmt = $db->prepare("SELECT id, name, color FROM Cars WHERE color = ?");
// execute/run the statement.
$stmt->execute(array($_POST['color']));
// fetch the result.
$cars = $stmt->fetchAll(\PDO::FETCH_ASSOC);
var_dump($cars);
}
Now, as you can probably tell, I haven't used anything to escape/sanitize the value of $_POST["color"]. And this code is secure from myql-injection thanks to PDO and the power of prepared statements.
It is worth noting that you should pass a charset=utf8 as attribute, in your DSN as seen above, for security reasons, and always enable
PDO to show errors in the form of exceptions.
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
so errors from you database queries won't reveal sensitive data like your directory structure, database username etc.
Last but not least, there are moments when you should not trust PDO 100%, and will be bound to take some extra measures to prevent sql injection, one of those cases is, if you are using an outdated versions of mysql [ mysql =< 5.3.6 ] as described in this answer
But, using prepared statements as shown above will always be safer, than using any of the functions that start with mysql_
Good reads
PDO Tutorial for MySQL Developers
There is none*! The object of PDO is that you don’t have to escape anything; you just send it as data. For example:
$query = $link->prepare('SELECT * FROM users WHERE username = :name LIMIT 1;');
$query->execute([':name' => $username]); # No need to escape it!
As opposed to:
$safe_username = mysql_real_escape_string($username);
mysql_query("SELECT * FROM users WHERE username = '$safe_username' LIMIT 1;");
* Well, there is one, as Michael Berkowski said! But there are better ways.
$v = '"'.mysql_real_escape_string($v).'"';
is the equivalent of $v = $this->db->quote($v);
be sure you have a PDO instance in $this->db so you can call the pdo method quote()
There is no need of mysql_real_escape_string in PDO.
PDO itself adjust special character in mysql query ,you only need to pass anonymous parameter and bind it run time.like this
Suppose you have user table with attribute name,email and password and you have to insert into this use prepare statement like this
you can pass name as => $name="Rajes'h ";
it should execute there is no need of equivalent of mysql_real_escape_string
$stmt="INSERT into user(name,email,password) VALUES(:name,:email,:password)";
try{
$pstmt=$dbh->prepare($stmt);//$dbh database handler for executing mysql query
$pstmt->bindParam(':name',$name,PDO::PARAM_STR);
$pstmt->bindParam(':email',$email,PDO::PARAM_STR);
$pstmt->bindParam(':password',$password,PDO::PARAM_STR);
$status=$pstmt->execute();
if($status){
//next line of code
}
}catch(PDOException $pdo){
echo $pdo->getMessage();
}
The simplest solution I've found for porting to PDO is the replacement for mysql_real_escape_string() given at https://www.php.net/manual/en/mysqli.real-escape-string.php#121402. This is by no means perfect, but it gets legacy code running with PDO quickly.
#samayo pointed out that PDO::quote() is similar but not equivalent to mysql_real_escape_string(), and I thought it might be preferred to a self-maintained escape function, but because quote() adds quotes around the string it is not a drop in replacement for mysql_real_escape_string(); using it would require more extensive changes.
In response to a lot of people's comments on here, but I can't comment directly yet (not reached 50 points), there ARE ACTUALLY needs to use the $dbh->quote($value) EVEN when using PDO and they are perfectly justifiable reasons...
If you are looping through many records building a "BULK INSERT" command, (I usually restart on 1000 records) due to exploiting InnoDb tables in MySQL/Maria Db. Creating individual insert commands using prepared statements is neat, but highly inefficient when doing bulk tasks!
PDO can't yet deal with dynamic IN(...) structures, so when you are building a list of IN strings from a list of user variables, YOU WILL NEED TO $dbh->quote($value) each value in the list!
So yes, there is a need for $dbh->quote($value) when using PDO and is probably WHY the command is available in the first place.
PS, you still don't need to put quotes around the command, the $dbh->quote($value) command also does that for you.
Out.
If to answer the original question, then this is the PDO equivalent for mysql_real_escape_string:
function my_real_escape_string($value, $connection) {
/*
// this fails on: value="hello'";
return trim ($connection->quote($value), "'");
*/
return substr($connection->quote($value), 1, -1);
}
btw, the mysqli equivalent is:
function my_real_escape_string($value, $connection) {
return mysqli_real_escape_string($connection, $value);
}

Escaping Quote for Variable in SQL Call

How do you add a single quote to a variable within a SQL statement? If I put 'jeremy' in place of the '\$user'\ variable it works perfectly. I can't figure out how to escape the quote for the variable in the SQL statement. Thank you for your help.
$resultArticles = mysql_query("SELECT COUNT(id) FROM articleList WHERE user = '\$user'\ ");
$totalArticlesLeaderboard = mysql_result($resultArticles, 0);
echo "<strong>Total Articles: </strong>" . $totalArticlesLeaderboard;
I've tried to find a suitable duplicate of your question, but I only found real dupes which are based on the ancient mysql_* functions. The mysql_* functions (like the ones you are using) are no longer maintained by the PHP commuity (for some time now) and the deprecation process has begun on it. See the red box?
You should really try to pick up the better PDO or MySQLi. Both of these option should be fine. Imho PDO has a better API, but mysqli is more towards mysql (in most cases PDO will do whatever you want to use it for).
With the two "new" API there is also the possibilty to use prepared statements. With prepared statements you should not have to worry about manually escaping values before inserting them into your queries.
An example of this using the PDO API would be:
$db = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $db->prepare('SELECT COUNT(id) FROM articleList WHERE user = :user');
$stmt->execute(array('user' => $user));
As you can see the values are not inserted directly into the query, but instead it uses placeholders. This code will make it impossible for people to inject arbitrary SQL into your query. And also you don't need to do any escaping anymore.
If you need more help in deciding between PDO or mysql check out the docs with more information about it. If you choose PDO you can find a good tutorial on the topic here.
Test this
$resultArticles = sprintf("SELECT COUNT(id) FROM articleList WHERE user='%s",
mysql_real_escape_string($user));
You should be able to just remove the escape characters:
$user = mysql_real_escape_string($user);
$resultArticles = mysql_query("SELECT COUNT(id) FROM articleList WHERE user = '$user'");
If you ever have trouble with variables, you can always just end the string and concatenate. I do this often to avoid confusion:
$user = mysql_real_escape_string($user);
$resultArticles = mysql_query("SELECT COUNT(id) FROM articleList WHERE user = '".$user."'");
As PeeHaa said, make sure you try to use PDO or MySQLi.
Don't forget to escape all user input, or they potentially can destroy your database. If you are using MySQLi, you can use mysqli::real_escape_string. Sanitizing ALL your user data is absolutely essential. DO NOT SKIP THIS!
If the variable $user contains any special characters, it is necessary to escape these, as shown in the first answer. If you don't have the mysql_real_escape_string() function available, use addslashes().

Data extraction using mysql_real_escape_string()

I am trying to retrieve values from the database using mysql and PHP.
The problem is :
+++ My table field (product_model_name) consist of (;) e.g Crystal;Uni and i want to filter results according to this product range.
I have tried to use mysql_real_escape_string() to deal with it but couldn't succeed.Here is my code:
$range="Crystal;Uni";
$test=mysql_real_escape_string($range);
$sql="select product_model_image from product_models where product_model_name=".$test;
$res= mysql_query($sql) or die (mysql_error());
while($row = mysql_fetch_array($res))
{
echo $row['product_model_image '];
}
Can anybody point me where i am making mistake??
try
$sql="select product_model_image from product_models where product_model_name= '{$test}'";
also use the pdo or mysqli instead mysql_*
Here is good PDO tutorial
Wrap your string in quotes in the query:
$sql="select product_model_image from product_models where product_model_name='".$test."'";
Obligatory side note: mysql_* library is being phased out so you should write new code in another library such as PDO or MySQLi. There are many other benefits to these libraries anyway, such as parameterised queries which are more secure than escaping as you are doing now.

PHP Mysql Auto Quote?

When inserting a row in mysql database, string values need to be enclosed in quotes where integer don't need to.
Is there any class or library that takes care of this automatically so that I can just pass to a 3rd-party function an array of fieldnames and values and don't have to worry about putting string values in quotes?
Thanks,
You need to worry about more than just quoting; you need to worry about SQL injection.
For new code, use PDO instead of the mysql_ or mysqli_ functions. Within PDO, use prepared statements (the PDOStatement object).
With prepared statements, you never have to enclose things in quotes and it stops SQL injections.
If you use PDO, then you do not need to worry about things like that.
Take a look at PDO::prepare for some examples.
When I'm using drupal, the default behavior of db_query("SELECT col FROM tab WHERE id=%d",$id) handles that for you.
This is similar to using sprintf with mysql_real_escape_string on your query first. And you could implement it yourself, from the code they show, note that they use the preg_replace_callback() method, and you can click on that..
The traditional way, if you ignore PDO (not recommended):
<?php
// Connect
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
OR die(mysql_error());
// Query
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
?>

Categories