Effective protection function against SQL injection - php

I found this sanitizing function in a free software:
function VerifChamps($valeur)
{
$verif = (get_magic_quotes_gpc()) ? htmlentities($valeur, ENT_QUOTES) : addslashes($valeur);
return $verif;
}
The query is then done like this:
$login=VerifChamps($_POST['name']);
mysql_select_db(..., ...);
$query = sprintf("SELECT * FROM table WHERE login='%s'", $login);
$Result = mysql_query($query, $connexion) or die(mysql_error());
$row_RsProf = mysql_fetch_assoc($Result);
mysql_free_result($Result);
How safe is this code? How is it possible to improve it to make it even more secure?
EDIT: the server is running PHP v5.2.13, with Magic Quotes turned on

The short answer is that it's not safe at all.
Here's what's wrong with it...
You're checking get_magic_quotes_gpc, which has been removed from PHP for years
You're using htmlentities to encode the string if magic quotes is on, but not if it's off (way to corrupt your data)
Why are you using htmlentities at all to send data to the database? It doesn't prevent sql injection at all.
addslashes doesn't take the client connection character encoding into account when escaping your data (which makes it very unsafe)
You're returning an undefined variable (i.e. NULL) making the entire function useless
Also, mysql was deprecated and has been removed from PHP 7. Use the newer MySQLi extension instead.
You can simply replace your entire function with the functionality provided by newer database APIs like MySQLi and PDO which offer prepared statements and parameterized queries, which are already proven to be reliable and secure. The code you're providing in your example here is clearly ancient and very insecure.

For many days, i am using mysqli_real_escape_string function. It's a good function to avoid sql injection.
And, please avoid mysql extension.This extension will be removed in the future. Instead, the MySQLi or PDO_MySQL extension should be used.

You want to use prepared statements
http://www.w3schools.com/php/php_mysql_prepared_statements.asp

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);

PDO and Escaping Input: Is this the safest way?

I wanting to check myself before I go live. I read so many different things on the internet but I want to know if this will absolutely protect my code for SQL Injection. If not, what do I need to add or take away?
$idtoapprove = mysql_real_escape_string($_POST['idtoapprove']);
$getcity = $conn->prepare('SELECT city, state FROM needs WHERE ID=:idtoapprove');
$getcity->bindParam(':idtoapprove', $idtoapprove);
$getcity->execute();
$cityrow = $getcity->fetch();
$needcity = $cityrow['city'];
$needstate = $cityrow['state'];
echo "$needcity, $needstate";
No need for mysql_real_escape_string here, actually, it's flat-out wrong (it's from a different, deprecated database library) and can damage your data. (Also, it would be ineffective here anyway - mysql_real_escape_string() is for escaping strings, it is useless for integers.)
The PDO prepared statement is enough.

Should I use mysqli_real_escape string() or mysql_real_escape_string() for form data? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
mysql_escape_string VS mysql_real_escape_string
I need to get company_name (given by user through a form) entered into my mysql database.
When I use
$company = mysqli_real_escape_string($_POST['company_name'])
I get an error
Warning: mysqli_real_escape_string() expects exactly 2 parameters, 1 given in /opt/lampp/htdocs/Abacus-Version-2/admin/Company/insert_company.php on line 58
But everything seems to fine while using
$company = mysql_real_escape_string($_POST['company_name'])
What can I do in such cases?
The one to use depends on whether you are using the MySQLi extension or the MySQL extension
// procedural mysqli
$db = new mysqli;
$sql = sprintf("INSERT INTO table (id,name,email,comment) VALUES (NULL,'%s','%s','%s')",
mysqli_real_escape_string($db,$name),
mysqli_real_escape_string($db,$email),
mysqli_real_escape_string($db,$comment) );
// mysql
$conn = mysql_connect();
$sql = sprintf("INSERT INTO table (id,name,email,comment) VALUES (NULL,'%s','%s','%s')",
mysql_real_escape_string($name,$conn),
mysql_real_escape_string($email,$conn),
mysql_real_escape_string($comment,$conn) );
mysql_real_escape_string() is designed to make data safe for insertion into the database without errors. (IE such as escaping slashes so that it doesn't break your code).
You should use mysql_ or mysqli_ functions to match your connection string. "mysqli" is the object oriented implementation of the mysql set of functions, so the functions are called in the object oriented style. "mysql" is procedural. I'd suggest changing over to "mysqli" because I believe there has been talk of depreciating the "mysql" functions in future versions.
If you connection string is:
mysql_connect()
then use:
mysql_real_escape_string($_POST[''])
If it is:
$mysqli = new mysqli();
then use:
$mysqli->real_escape_string($_POST[''])
Definitely NO
Both functions has nothing to do with form data.
They have to be used to format string literals inserted into SQL query only.
This function belongs to the SQL query, not to whatever form. And even to very limited part of the query - a string literal.
So, every time you're going to insert into query a string literal (frankly, a portion of data enclosed in quotes), this function ought to be used unconditionally.
For the any other case it shouldn't be used at all.
As for the error you're getting - it's pretty self-explanatory: this function expects 2 parameters, not one. Just pass proper parameters as stated in the manual page for this function, and you'll be okay
It should be this if you use Procedural style:
$city = mysqli_real_escape_string($link, $city);
where link is the connection
or this when you use Object oriented style:
$city = $mysqli->real_escape_string($city);
Check out the php manual:
http://php.net/manual/en/mysqli.real-escape-string.php
Since all the MySQL extension is being deprecated, you'd best use the MySQLi methods instead, it's more future proof.
Both variants are fine* (Please look at my Update).
When you are using a mysql_connect then you should stick to mysql_real_escape_string() and also pass the connection handle.
When you are using a mysqli_connect then you should stick to mysqli_real_escape_string().
UPDATE
As pointed out by Jeffrey in the comments, using mysql_ functions is NOT fine. I agree to that. I was just pointing out, that you need to use the function that is used by the MySQL-extension you are using.
It came to me, that it was not the question, which MySQL-extension to use, but which function for escaping data.
If you ask me:
Use mysqli or PDO, because mysql is not recommendable and deprecated.
Pass the Connection Handle to the escape-function or better
use prepared Statements (PDO-Style)

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);
}

How to use $_GET securely?

I need to use a get function to retrieve $title variable from a url.
$title=$_GET["title"];
The $title is later used in a MySQL query.
The question is how to make this secure?
In other words, how to neutralize any malicious codes sent through the URL.
(For a value of "secure" equal to "to prevent it breaking the database"): use any database API that uses bound parameters.
Bound parmeters tend to let the database handle the escaping (so uses escaping routines written by the database authors rather then the language authors) and uses a syntax that is less prone to being forgotten about for that one vital escape then manually escaping each piece of input data with (for example) mysql_real_escape_string.
You might need to take other steps later before you do something with the data in a different context (e.g. to make it safe to insert into an HTML document)
You must use mysql_real_escape_string() to escape all characters that could interfere with you database. If you're displaying this title, you should also make use of htmlentities() or striptags()
As of PHP 5.2, you can use filter_input() and filter_input_array() to sanitize and validate the the $_GET or $_POST data.
For example:
$my_string = filter_input(INPUT_GET, 'my_string', FILTER_SANITIZE_STRING);
Read more about that in this article here.
For SQL queries, it's very recommended that you use PDO with prepared statements to protect from SQL injections. You can read about PDO in the PHP Manual here.
You can use mysql_real_escape_string function (Escapes special characters in a string for use in an SQL statement)
Php Manuel
Use query parameters. There is a number of different ways to connect to mysql from PHP, and they way to use parameters varies a little from framework to framework. Here is an example using PDO:
$dbh = new PDO('mysql:dbname=test;host=127.0.0.1', 'username', 'password');
$sth = $dbh->prepare("select * from table where title = :title")
$sth->execute(array(':title' => $_GET["title"]));
$rows = $sth->fetchAll();
var_dump($rows);

Categories