Short Solution for SQL Injection Attacks with MySQLI - php

I've gotten into the habit of writing the following sort of code:
$q = mysqli_query($mysqli,"SELECT * FROM table WHERE a='$a', b=$b;");
while ($row = mysqli_fetch_array($q)) {
// do something
}
Where $a is a string entered by the user (gotten through $_GET) and $b is a user-entered integer.
Obviously the code I have above is vulnerable to SQL injection attacks, so my habit is to rewrite it like this:
$q = mysqli_query($mysqli,"SELECT * FROM table WHERE a='".str_replace("'","",$a)."', b=".($b+0).";");
But this of course has problems if $a needs to have apostrophes (or quotation marks when quotation marks are used to mark the string).
Recently I learned about prepared statements in mysqli and started playing around with them. I wrote the following function to make it easier to make calls without having to change much of my code:
function safequery($a,$b,$c) {
global $mysqli;
$q = mysqli_prepare($mysqli,$a);
$e = "mysqli_stmt_bind_param(\$q,\$b";
$i = 0;
while ($i < count($c)) {
$e.=",";
$e.="\$c[$i]";
$i++;
}
$e.=");";
eval($e);
mysqli_stmt_execute($q);
return $q;
}
safequery("SELECT * FROM table WHERE a=? AND b=?;","si",array("unsafestring",37));
But what is returned from this function turns out not to be a mysqli_result and thus doesn't work with the first bit of code above. After some more research, I found an alternative, but it would require a complete rethink of how I write my code. Is this necessary or is it possible to protect against MySQL injection attacks with only small changes to the first bit of code (no new lines, same output style, etc.)?
I have looked around on StackOverflow and the rest of the web but I can't find a good simple solution; all of them require the edition of at least three more lines for every call and a different way of reading each row. I'd prefer to do this procedural-y...

Don't think half-measures are going to solve this problem. Commit to expunging all of the interpolation bugs from your code and be disciplined about using prepared statements. Your proposed fix only makes things worse, it gives you a false sense of security. It's also considerably more work than using prepared statements so I'm not sure why you'd even bother doing it this way.
One way to make this a lot easier to do is switch from using double quotes " to single quotes ' on your queries to disable interpolation. Any escaping errors become syntax problems, and if your editor highlights those you'll be able to spot them from across the room, and if something does by fluke work you'll be inserting harmless things like $a instead of actual data.
Another thing to consider is if you should be using an ORM like Doctrine or Propel given what you know about the sophistication of your application. These can make things considerably easier from an implementation perspective.
The code you have there is a ticking time bomb, get rid of it as soon as you can. Don't think replacing quotes is enough, that solves just one issue, there's actually a number of other methods your application can be vulnerable to injection bugs. Tools like SQLMap have an entire arsenal of things they can try to break your code and if you look at the list of things it can do if it finds a flaw you'll probably want to fix these problems right away.
One way you can find issues is using a tool like grep:
grep query `find -name '*.php'` | grep '\$'
That's not bulletproof, but it should probably turn up a lot of code you should fix right away.
Also as #ceejayoz suggests, purge that function with eval in it from your computer and never, ever do that again.

After talking with the commenters and looking at some of the other questions and things they linked to and suggested, I've rewritten the third code snippet to both solve the problem in question and fix the security holes that several commenters pointed out (if there are any remaining ones, please tell me).
First on my use of eval(). Though I can't see any immediate way it could cause problems (user strings are not executed as code in the eval()) it is certainly a round about and stupid way of solving my problem. #TadMan suggested call_user_func_array() which, once worked out, looks something like this:
function refValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0) //Reference is required for PHP 5.3+
{
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}
function safequery($a,$b,$c) {
global $mysqli;
$q = mysqli_prepare($mysqli,$a);
call_user_func_array("mysqli_stmt_bind_param",refValues(array_merge(array($q,$b),$c)));
mysqli_stmt_execute($q);
return $q;
}
safequery("SELECT * FROM table WHERE a=? AND b=?;","si",array("unsafestring",37));
It turns out that mysqli_stmt_bind_param() takes only references, thus the new refValues() function (run into and solved before on StackOverflow: https://stackoverflow.com/a/16120923/5931472).
While this removes eval() and makes my code easier to understand, it still doesn't solve the original problem of returning the query response in a way that mysqli_fetch_array() can use. It turns out that the proper function to do this is mysqli_stmt_get_result() so the last line of safequery() is rewritten from:
return $q;
To:
return mysqli_stmt_get_result($q);
The result of safequery() is then a mysqli_result which can be used by mysqli_fetch_array().

Related

Upgrading PHP - Need to remove get_magic_quotes_gpc

We're upgrading from php 5.3 to 5.4, which is not backwards compatible for 'get_magic_quotes_gpc'. I understand the code will still work, sort of, but just bring back a FALSE each time.
However, I think the time has come to scrub this from our code.
Here's a typical example:
$product_id = "0";
if (isset($HTTP_GET_VARS["id"])) {
$rid = (get_magic_quotes_gpc()) ? $HTTP_GET_VARS["id"] : addslashes($HTTP_GET_VARS["id"]);
}
//then $product_id gets used all over the place in many different queries
I've been researching how to fix this and this is what I came up with:
$rid = "0";
if (isset($HTTP_GET_VARS["id"])) {
$rid = addslashes($HTTP_GET_VARS["id"]);
}
I'm a little over my head here. I know this all has to do with SQL injection and such. Is my solution an reasonable/acceptable one?
Thanks in advance.
<<<< EDIT - ADDITIONAL INFORMATION >>>>
Thanks for the replies. Actually, we did a bunch of conversion to PDO about 18 mos ago (mostly due to this type of advice on stackoverflow :)
So, I may have some reduntant, pointless code going on. Here's the full picture of what is happening below the code I posted above that gets the variable from the URL.
You'll see, there is the (get_magic_quuotes_gpc) that used to be there, now commented out and replaced by the (addslashes). But that variable is passed on to a PDO query.
$product_id = "0";
if (isset($HTTP_GET_VARS["id"])) {
//$product_id = (get_magic_quotes_gpc()) ? $HTTP_GET_VARS["id"] : addslashes($HTTP_GET_VARS["id"]);
$product_id = addslashes($HTTP_GET_VARS["id"]);
}
// NEW QUERIES - BEG xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
try {
# MySQL with PDO_MYSQL
$pdo = new PDO("mysql:host=$hostname_db;dbname=$database_db", $username_db, $password_db);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// Query 1: product details
$stmt = $pdo->prepare('SELECT
[a bunch of stuff here, fields, joins, etc]
WHERE product_id = ? ');
$stmt -> execute(array($rid));
$row_count_resto_details = $stmt->rowCount();
$row_resto_details = $stmt->fetch(PDO::FETCH_ASSOC);
}
// Error message for pdo
catch(PDOException $e) {
echo $e->getMessage();
}
// END QUERY xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Can I just get rid of all the stuff in the first 4-5 lines of code and just make it this:
$product_id = $HTTP_GET_VARS["id"];
No, it's not reasonable.
The problem is, the "magic quotes" feature was a bad idea in the first place, so trying to replicate it only means that you've relied on a broken solution until now, and your application is without a doubt vulnerable to SQL injection attacks.
"Why is magic quotes a broken solution?", you'd probably ask. And the answer is kind of hidden in the question itself - security and IT in general aren't and can't be magic. Whenever you see a solution that advertises itself or at least seems to work in a "magic" way, know that it is bad and you should never trust it.
What you need instead are context-aware solutions, and in the case of preventing SQL injections - that's parameterized queries. You should read this to learn more: How can I prevent SQL-injection in PHP?
I'd also urge you to upgrade straight to PHP 5.6, mostly for two reasons:
PHP 5.4 will reach its End Of Life in a month and that alone makes it a possible security risk.
You have no reason not to. Honestly, the upgrade path is a breeze and comes with very little backwards-compatibility concerns, if any at all. PHP is much more stable now, there are very few significant changes since 5.3 vs 5.4.
Update (to answer the extended question):
You not only can remove the addslashes() logic, but you MUST do that - if you leave it, it will add slashes to some of your input data and these slashes will be a part of the data itself.
What you want to do instead is to validate input data - check if it is in the proper format in the first place. For example, if you expect a numeric ID - check if it only contains digits before using it.
Also, $HTTP_GET_VARS has been deprecated since PHP 4.1 and you should be using $_GET instead.

Problems with converting mysql over to mysqli errors with mysqli_query & mysqli_fetch_row

Here is the edited script without errors. And the 2 fixes applied to it. To those who helped in part, thank you. To mentions that the code is unclear or messy is inconsequential. Given that most of the following is common structure in mysql queries. Even the example documentation for mysql followed this similar flow. Members who reply should negate from pointless internet banter. Its more worth your time, and my own to do so. Those who stayed on topic and assisted, I thank you.
For example:
$row = mysqli_fetch_row(mysqli_query($con, "SELECT test_table.points FROM test_table WHERE test_table.key = '" . $key . "'"));
if ($row[0] > 0){ // exists
Where $row will return a non-zero result if true. Otherwise 0 on false. There is little need to check mysqli_fetch_row and/or mysqli_query. Since checking $row in simplicity works fine. It is unneeded to check mysqli_fetch_row and/or mysqli_query individually in a general exists condition. It does accurately provide exist / does not exist results. There is no $result $row $query just $row.
The noted deviation to that normal flow was my desire to use call_user_func. And to poll in func and params through $_GET. Will be looking more at PDO. However, the clean code before exec should do alright job for now. Which is to clean before exec.
All in all, the code works just as it should. And have since written more to manage a mysql database. From write, write chunk, read, read chunk, delete, delete chunk.
Also to collect numbered records on request. For example say you have 6 records for the same John Smith. You can now collate and scan for differences in those records. Either for what you want, dont want, etc. Or if say you just want to blindly call the first 3 of those records for John Smith.
mysqli_fetch_row & mysqli_fetch_row fix :
FROM Calling $con outside function then into as per mysql. Which in mysqli does not work as expected. There was no error with the functions, over how $con was being handled.
TO Calling $con inside function with just the added global $con. May end up using $GLOBALS even for this.
Result : Calling $con outside function then in works fine in mysql. In mysqli it requires global be set within the function. ie global $con. Or it fails.
call_user_func non-critical error fix :
FROM call_user_func($func($_GET['user'],$_GET['key'],$_GET['points'],$_GET['type']));
TO call_user_func($func,$_GET['user'],$_GET['key'],$_GET['points'],$_GET['type']);
Result : Both lines execute correctly. From executed with a non-critical error. TO does the same thing, but with no following non-critical error.
Sample Output for both : user=MY_Name;key=34342$ee56i1;points=1234;type=
-- code removed as fixes solved the issues --
You are using call_user_func wrong read the manutal
call_user_func first parameter is the callback - in your case it's a function inside your class so it should be something like this:
If you have a non-static function in an object:
class Test{
public function doit($a){
echo($a);
}
}
$t = new Test();
call_user_func(array($t,'doit'),'asfaasfs');
and in static functions inside object:
class Test{
public static function doit($a){
echo($a);
}
}
call_user_func('Test::doit','asfaasfs');
You have a few problems.
$con is declared outside the class, and is thus not available inside the class. You need to pass it into the class (the better option), or specify it as a global (the quick+dirty option).
mysqli_fetch_row(mysqli_query($con,'...'))
This code is obviously converted directly from your old mysql_xx() code, but it's not great.
You're ignoring any possible error condition that is returned by mysqli_query(). This means that if it fails, it'll pass false into the mysqli_fetch_row() function, which will then fail with a meaningless error expects parameter 1 to be mysqli_result, rather than actually telling you what the error was in the query.
The thing is, because of my first point above, with $con not being set, mysqli_query() is failing, and this is why you're getting the error in mysqli_fetch_row().
Ideally, you should split this code out into multiple lines. Call mysqli_query() on its own, then do some error checking, then call mysqli_fetch_row() only once you know that the query actually worked.
Hope that helps explain what the problems are here. Solve those two points, and you should be well on the way to sorting the whole thing out.
Once you've got rid of those fatal errors, you should also take time to work on the problem that your code is vulnerable to SQL injection attacks. You're currently passing your $_GET variables directly into the query strings without any sanitisation. This will make your system very fragile and easy to hack. You should consider using Parameterised Queries, which is a feature of the mysqli library designed to make it easier to deal with variables in SQL queries in a safe and secure way.
Your class is pointless at the moment, perhaps stick to writing imperative style code as it will at least be cleaner.
At the moment, you should pass $con to your MYsql class to use itself as a resource, not try to access it as a global variable.
Your are not filtering your user's input either, this is dangerous and could lead to SQL injection attacks on your site.
I'd encourage you to read through these two articles, and once you grok them, I'd also encourage you to simply switch to using PDO with prepared statements. This will stop SQL injection attacks that your code currently allows.
http://net.tutsplus.com/tutorials/php/pdo-vs-mysqli-which-should-you-use/
http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/

Database class in PHP; only has one function - question about practices and whether it's a good idea

So I have this database class in PHP and I only have 1 function in it (other than __construct and __destruct. Let me explain further...
I had originally written it so when I connected to a database I would just call my function connect_to_db() which returned a mysqli object. I then used this objects functions (->query(), ->prepare(), ->bind_param(), et cetera..) to do whatever. This cluttered (and still is as I haven't switched my code over to my new class yet) with a lot of functions that just do specific things, for example:
function get_country_info($db, $usrid) {
$statement = "select `name`, `population`, `money`, `food` from `countries` where `usr_id` = ?";
$qry = $db->prepare($statement) or
trigger_error("get_country_info():statement failed...");
$qry->bind_param("i", $usrid);
$qry->execute();
$qry->bind_result($name, $population, $money, $food);
$qry->fetch();
$res = array("name" => $name,
"pop" => $population,
"money" => $money,
"food" => $food);
return $res;
}
And what I originally planned to do was just to throw these into a class for clarity, but what I actually ended up doing was creating a class that when created creates a mysqli object for a specific database (supplied via an argument) and when destroyed closes off this link. I very much like not having to worry about typing $db->close(); as when the script finishes executing the connection is closed.
It only has 1 other function; query(). This function can handle any query put forth and outputs it as a multidimensional array. It uses eval(). From what I understand this is generally frowned upon - but eval() is so useful; so why is it frowned upon?
I guess the function may be slow, but seen as I'm just using it for a pet project (browser based country management game) and I haven't noticed anything I'm not worried about that at all. What I am worried about is whether people would generally do this in the 'real world' or whether there is some sort of standard by which people do this, or perhaps something included (or add-on-able) in PHP which is usually used?
I'm self taught, so sometimes I don't really know the best way to go about doing things. Perhaps somebody could advise me here?
The function in question can be seen here: http://pastebin.org/353721, as its ~60 lines and I don't want to clutter the page. I also haven't extensively tested it (I don't even know what unit tests are, so I test by using the function in a lot of different ways) so it may have problems I'm not aware of that you guys can point out.
Thanks.
Doesn't seem to me too bad. You have basically done a really basic wrapper around the database, and you performed the very first step in database independence, which is good.
This can be good for small and well organized projects, but once you will start going more complicated, you will soon notice that your approach has one large disadvantage: you still have your SQL queries split around the site. The day you will change anything in the database, you'll need to go through all your site and look for all the SQL statements: this is bad (I had to do it once...).
You should now move all the SQL code to one place. So there are various options. In a similar context, I made the query() method protected, then made the Db class "abstract" and subclassed it. Each subclass is a class which contains several methods relative to a specific set of tables, and this is the only place where you find SQL. All the rest of the project can only call these methods.
Or, even better, you could use an ORM (oblect relational mapper) which would map each table to an object.
For what concerns the evils of evals: I never used them. But I thought I wasn't going to use a "goto" because it's evil, and then I found the magic place where that was the perfect fit. So, if you have investigated all the possibilities, and you think that's the optimal solution... use it.
Instead of eval, you can use call_user_func() or call_user_func_array().
You should check the return value of execute().
Your function does not support subselects which contain multiple comma's, but only return one value.
You can use trim() instead of ltrim(rtrim()).
I would still use a function like get_country_info() on top of this db class. Often, you want to do something with the data before your application can use it. More importantly, you want to abstract the data storage from your application. That is, the method which uses the country info does not need to know that it came from the database.
As Techpriester wrote: brake it down into smaller parts.
I recommend at least:
the argument to bind converter
the single and multi param bind if-else branch
the sql statement parser (find out about returned fields)
One other approach to your problem would be to build the sql statement inside your query class (arguments would be field names, the table, the where constraints,... ) and to develop subclasses for different query types. This would elimiate the need to parse the statement.
Above this layer you would put a bunch of DAO classes to do the actual work.
But wait: others have done this... (maybe a lot of others to be specific). So using PDO, Doctrine, Propel or even a bigger library like ZendFramework (active record pattern there...) would be the most valuable and stable option.
If you, however, want to learn something about software architecture and OO Systems. Go ahead and build your own, if you do it well you can switch to another DB Layer as soon as your system grows (Version 2.x :-) ).
First: The eval() in your function doesn't serve any purpose as I see it. Why don't you call the $qry->... things directly?
Second, your function is way to complex. Brake it down into smaller parts that call each other.
Third: Manipulating SQL Statements is generally a very bad idea. It's error prone as soon as you feed your function with something like nested statements or other more complicated SQL code. So just don't do it.
Fourth: I wouldn't recommend using mysqli anymore. You should switch to PDO.
As I understand it, your function tries to find out, what fields were in the SELECT clause of the query to build the result array. That is only necessary if you want to allow your database layer it to execute arbitrary queries which is also not a good idea.
When I have to use classic SQL in an application, I predefine every query that I need in some method or function. That function then will know exactly what field it has to read from the result set. So there's no need to parse the SQL code. However, mostly I try to avoid SQL by using things like Doctrine ORM. SQL is just too prone to errors...
About eval(): It is entirely and absolutely evil for several reasons:
It may open the door to code injection.
It makes code unreadable to humans and unparsable to an IDE
It's nearly impossible to debug code that uses eval()
Not really a problem of eval() itself, but when you have to use it, that's a sign of a flawed design.
To your question - you need some experience to learn why there are "best practices", why eval() is deprecated, why people use prepared statements etc.
I'd recommend you to have a look at http://dibiphp.com/cs/ for a nice and concise DB layer for PHP.
You could also try Java when you get some clue about web technologies.
Then you can use cool things like iBatis, which almost got it to PHP
I personally once had a lib for DB, which was used like this:
$aasAreas = Array();
$sSQL = "SELECT id, x, y, x2 AS r, popis FROM ".$oFW->GetOption('tables.areas')
." WHERE id_ad=".asq((int)$_GET['id']);
$oRes = $oFW->GetDB()->Select($sSQL);
if(!$oRes || !$oRes->IsOk()){ $sError = $oRes->GetError(); break; }
else while( $a = $oRes->FetchRow() ){
$aasAreas[] = $a;
}
[OT] And some ORM for PHP attempt, used like this:
// Load by ID
echo "<h3>Load by ID</h3>";
$iID = 1;
echo "<pre>\$oObject = \$oOP->LoadObjectById(".$oClass->GetName().", $iID);</pre>";
$oUser = $oOP->LoadObjectById($oClass, $iID);
echo "<pre>oUser: [".gettype($oUser)."]".AdjustedPrintR($oUser)."</pre>";
echo "<div>GetPoolCount(): ".$oOP->GetPoolCount()."</div>";
// Save
echo "<h3>Save</h3>";
$oUser = new cObjectPersistenceTestClass_User();
$oUser->SetId(1);
$oUser->SetProperty('user', 'as'.rand());
$oUser->SetProperty('pass', 'as');
$oUser->SetProperty('fname', 'Astar');
$oUser->SetProperty('lname', 'Seran');
echo "<pre>oUser: [".gettype($oUser)."]".AdjustedPrintR($oUser)."</pre>";
$bSucc = $oOP->SaveObject($oUser);
echo "<div>".($bSucc ? 'saved' : 'error')."</div>";
// Load by value - load object created above -> Object Pool hit
$xVal = $oUser->GetProperty('user');
$aoUsers = $oOP->LoadObjectsByValue($oClass, 'user', $xVal);
echo "<pre>\$aoUsers: [".gettype($aoUsers)."]".AdjustedPrintR($aoUsers)."</pre>";
etc.

Function to sanitize input values PHP

I use this:
function safeClean($n)
{
$n = trim($n);
if(get_magic_quotes_gpc())
{
$n = stripslashes($n);
}
$n = mysql_escape_string($n);
$n = htmlentities($n);
return $n;
}
To prevent any type of MySQL injection or anything like that. Whenever I use it to wrap around $_POST like this:
$username = safeClean($_POST['user']);
$password = md5(safeClean($_POST['password']));
$vpassword = md5(safeClean($_POST['verify']));
$email = safeClean($_POST['email']);
It doesn't even work, but I have attached functions.php and the directory is correct but doesn't work at all because it just shows a blank page... If I remove the safeClean() from each $_POST it works.
How come this isn't working at all?
In my opinion, this sort of general sanitization approach isn't the best way to think about things. For one thing, parameterized queries (probably most convenient using PDO) are a much better way to approach the SQL safety issue. But in general...
I know the developer impulse is to try and reduce the number of things you have to think about. So, naturally, you want to see if you can come up with an all-purpose sanitization function you can just hand all inputs over to and not have to worry any more. Inputs are one arena, though, where if you really want security, you need to think specifically about what each incoming piece of data is supposed to be and where it's going to end up. If you go on auto-pilot here, you will introduce a security issue at some point.
Try using mysql_real_escape_string() rather than mysql_escape_string().
Almost everything in your code is wrong.
get_magic_quotes_gpc is misplaced, htmlentities is misplaced and even term "sanitization" is misused.
As a matter of fact, you shouldn't sanitize anything for the database. But just follow syntax rules.
Take a look at the very similar question, I've explained SQL matters pretty well: In PHP when submitting strings to the database should I take care of illegal characters using htmlspecialchars() or use a regular expression?
And as of the blank page, you have to learn primer of debugging. You have to turn error reporting on to see error messages instead of blank page. To start with it you can refer to this article:
Link to start: http://www.ibm.com/developerworks/library/os-debug/
you can start from adding these lines at the top of your cript
ini_set('display_errors',1);
error_reporting(E_ALL);
and this code to the query execution:
$result = mysql_query($query);
if (!$result) trigger_error(mysql_error());

What would be a better way of doing the following

if(get_magic_quotes_gpc())
{
$location_name = trim(mysql_real_escape_string(trim(stripslashes($_GET['location_name']))));
}
else
{
$location_name = trim(mysql_real_escape_string(trim($_GET['location_name'])));
}
That's the code I have so far. seems to me this code is fundamentally ... OK. Do you think I can safely remove the inner trim(). Please try not a spam me with endless version of this, I want to try to learn how to do this better.
UPDATE
So after reading some of the responses, I think I have come to understand a good method for safely getting data from a user, storing it and then displaying it back.
When you first load the page
$foo = trim($_GET['foo']);
if(get_magic_quotes_gpc())
{
$foo = stripslashes($foo);
}
Then when you come to use this variable as part of a SQL string, even if not storing the data in the database, you should escape it.
mysql_real_escape_string($foo);
And finally, if reading data from the database and wanting to display it as HTML, such a post on a blog or forum, you should pass the variable using htmlspecialchars
echo(htmlspecialchars($bar));
Would any one like to suggest a better set of functions to use? other then obviously wrapping these functions to make them simpler to call.
Here:
$location_name = trim($_GET['location_name']);
if(get_magic_quotes_gpc()) $location_name=stripslashes($location_name);
Then there is also the SQL injection protection, but don't do this until the very last moment before sticking this var in an SQL query. And even then don't apply the changes to the var itself, but rather a copy. You might want to show $location_name to the user afterwards (for example if the form fails). So
$sql="UPDATE whatever(location) VALUES('" . mysql_real_escape_string($location_name) . "')"
I'm assuming of course that $location_name will end up in the database; otherwise you don't need mysql_real_escape_string.
Finally you want to use htmlspecialchars if you're going to display $location_name on your page somewhere.
Edit: You want to use htmlspecialchars() just before displaying the data (definately don't save data that has already been transformed via htmlspecialchars in your database). In general you want to use escaping functions at the last moment and then on a copy of your var. That way you know that at any point during the script the var is the original one and is not carrying some random escape characters from a transformation that happened somewhere before.
You also know where your escape functions are/should be. sql escaping is near/at your sql query. XSS escaping (htmlspecialchars) is near the part where you display data in a web page.
Finally once you get the grip of things, you could always forego SQL escaping by using PHP's PDO functions. Also in the future you might want to take at look at this: Do htmlspecialchars and mysql_real_escape_string keep my PHP code safe from injection?
I am sorry to say but everything in your question is wrong.
First, it has nothing to do with performance, by any means. these functions never become a bottleneck and never cause any performance issue.
Next, You've choose wrong place to get rid of magic quotes. Magic quotes is input data related, not database related. It it is better to make a distinct function and place it in your configuration file, being included into every script. You can use one from here
So, the code become like this:
$location_name = mysql_real_escape_string(trim($_GET['location_name']));
But i strongly advise you not to mix database escaping with anything else, as anything else is optional while database escaping is strict and unconditional.

Categories