Log in

View Full Version : How to protect other files in Login folder etc



kuau
01-16-2012, 09:07 PM
In the past I have always used .htaccess to protect folders so this is my first attempt at an actual login script & I have some questions. So far I have done the Login and the Lost Password parts, and they work great, but are probably not as secure as they could be.

1. .htaccess protects all files in the folder but login does not. After reading posts from other people writing login scripts, I get the impression that you have to put require_once('login.php') (or something) at the top of each file in the folder and use sessions somehow. I have googled sessions and I still don't quite get it. Can someone please explain sessions from scratch?

2. Are sessions necessary for login scripts? They seem to be for logging users out after a set length of time, or remembering info from their last session. Can you control what values are stored in the session info? Are cookies files that store the session info?

3. I understand == but what does === mean?

4. Is this a good function to use to prevent SQL injection?

function clean($str) {
$str = @trim($str);
if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
return mysql_real_escape_string($str);
}

5. I know in php.ini that magic_quotes_gpc = On, so what does this mean...

if(get_magic_quotes_gpc()) {
$str = stripslashes($str);
}
and what does it accomplish security-wise? Do people use slashes in SQL injection?

6. Does this remove blanks at each end of a string? Anything else?
$str = @trim($str);

7. Is it necessary to md5 encrypt the passwords in the database? If encrypted, how do you send people forgotten passwords? If they are decryptable, couldn't anyone do it? So what is the point?

Thanks for any help. e :)

traq
01-16-2012, 11:53 PM
1. .htaccess protects all files in the folder but login does not. After reading posts from other people writing login scripts, I get the impression that you have to put require_once('login.php') (or something) at the top of each file in the folder and use sessions somehow. I have googled sessions and I still don't quite get it. Can someone please explain sessions from scratch?
if you are password protecting file-by-file, yes (and therefore, yes, it would only protect PHP pages). The simplest solution to this would be to have all of your password-protected PHP pages in one (non-htpasswd) folder, and all your other restricted files in a different folder.

2. Are sessions necessary for login scripts? They seem to be for logging users out after a set length of time, or remembering info from their last session. Can you control what values are stored in the session info? Are cookies files that store the session info?
strictly speaking, they're not necessary - though it would be inconvenient and counter-productive to avoid using them.

-- cookies store the session id on the user's computer.
-- php gets the cookie and finds the matching session info (actually stored in a tmp file).
-- session info is read/writable via the $_SESSION superglobal (once you start the session, of course).

keeping session info means that you can keep track of what the user is doing (for example, his name, his permissions, what steps of a process he's already completed, etc.).


3. I understand == but what does === mean?
== means "equivalent," whereas === means "(exactly) equal."

for example:
<?php
1 === 1
// true (both integers)

1 == '1'
// true (one integer, one string)

1 === '1'
// false (equivalent value, but different data types)

// this is most useful in the context of certain return values:

// executing some query //
// checking # of rows returned //
if( !$result ){ print "there was an error!"; }

// in fact, there may have been no error, just zero rows. observe:

0 == FALSE
0 == NULL
0 == '' // (empty string)
0 == '0' // ("0" as a string)
// all "true." in fact,
0 == "false" // ("false" as a string)
// and so on.

// realistically, "===" should be used in almost all cases.
// "==" is usually just laziness, oversimjplification, and/or ignorance :)


4. Is this a good function to use to prevent SQL injection?the best option is to make sure magic_quotes_gpc is TURNED OFF in your php configuration :)

you should still have a function like this, as a backup in case you can't affect the server configuration. it's easier to do it all at once, at the very beginning of the script. I'll find the code I use and post it later.


...and what does it accomplish security-wise? Do people use slashes in SQL injection?the slash is an escape character: it marks the following character as "literal" where it might have a special meaning otherwise. the most common case is a quote, which a hacker can use to end one SQL statement and begin another.


6. Does this remove blanks at each end of a string? Anything else?
$str = @trim($str);
read here (http://us.php.net/manual/en/function.trim.php) for the characters it removes. you can also specify other characters to remove by using the optional second parameter.


7. Is it necessary to md5 encrypt the passwords in the database? If encrypted, how do you send people forgotten passwords? If they are decryptable, couldn't anyone do it? So what is the point?it is very beneficial to encrypt passwords, since it makes it impossible to accidentally disclose someone's password -even if your database is compromised.

you don't send people their forgotten passwords. you send them a new, temporary password, so they can choose a new one themselves.

hashing functions like md5, sha1, etc., are not "decryptable," no.

djr33
01-17-2012, 02:40 AM
I agree with everything traq said. Just a few things to add:

1. Sessions are incredibly easy to use (once you understand them), and they're very helpful. First, include the following at the beginning of every page before any output of any kind, including even a blank line:

<?php //first line of your file, before any output
session_start();
/*......*/ ?>
Now you can use $_SESSION whenever and wherever you want. $_SESSION['myvar'], for example.
Session information is available for a single user during a single session. It is stored on the server, NOT in cookies, and it is completely secure. You could put your server admin password into $_SESSION and the user could never see it (don't do that, though!), unless you chose to show them. It's a way to track ongoing information for a single user. It's not reliable as a way to permanently store it, because it expires with the session. Sessions last somewhere between 15 minutes and forever, depending on the configuration.
Sessions use a cookie to link the session to the user, and otherwise they don't use cookies. So the session ID is stored in a cookie, the server figures out which session to use, and that's all.
The only problem there is that by stealing the session ID cookie, a session can be hijacked. But that's not very common and would require taking the file from the user's computer.
A nice trick with that is to use the current IP address to make sure that the session isn't hijacked (as an entry in the $_SESSION array). That's a tradeoff, though, since mobile devices or laptops might move IPs, but it's certainly very secure. Just check to be sure that stored session IP value still matches $_SERVER['REMOTE_ADDR'] for each page load, and it's the same connection.

2. Sessions aren't necessary, but they're useful. I really like them. There are plenty of systems that use cookies only, but they don't have a good way to store information from page to page for users, and they can be less secure (if designed badly). I'm still surprised at how many login systems don't use sessions, mostly because they are so easy.

3. It's useful to use both == and === because they do different things. Personally I use == unless I have a very specific reason to use ===. If you want to distinguish between false and 0, then use === (and a few other similar cases). If not, then you probably would want to use just == in case your number might be sent as a string, or anything like that. Most of the time it won't matter anyway, but it can be important sometimes.

6. Basically, yes, just whitespace.

7. Hashing and encryption are different. Hashing algorithms are strictly one-way so they aren't "encryption" and can't be "decrypted". It's a very simple (but powerful) principle: one-way hashing means that by following the same algorithm, you can check if two inputs are equivalent. So when they first set the password, you store the hashed password. Then next time you need to check their password, you take their submitted (raw) password, convert it using md5(), then see if it matches the stored md5() value. If it's the same, then it was the same input. If it's not the same, then it wasn't the same input. There's no way to decrypt it, so it's not hackable. In fact, some systems (although these aren't the most secure) actually store the hashed password in a cookie. (I'm not recommending that, just explaining how truly "secure" a hashed value is, assuming that the hashed value itself can't give access to the system on its own. That's the one weakness of a hashing system, but easy to avoid if you always require re-hashing before comparing.)
A couple notes:
1. The only weakness of hashing is that they're consistent and widely used, so there actually are some database projects out there that match up inputs and outputs, so in that sense they can be decrypted, but only by long term brute force. For that reason, it's a good idea to use a newer algorithm. md5() is very popular, but sha1() is a little newer and probably a better idea. It's no harder to use, and just generates a longer string (I think 40 chars instead of 32.)
2. Technically, it's possible for two passwords to have the same hashed value. It's incredibly unlikely, but this also helps for security: because it's not "1 to 1", you truly can't figure out what the password is, at least not definitively.
3. You can use "salt" to make it more secure. Instead of md5($pass), you can use md5($username.$pass), among other things.

traq
01-17-2012, 04:06 AM
slightly tangential (not-quite-off-topic):

md5's main weakness is that it's been around a while - as Daniel says, there are databases ("rainbow tables") of known input-output combinations (sha1 will eventually have a similar weakness). That's why he recommends using a "salt": an additional value prepended/appended to the actual password.

Beyond "salting," there is extending: instead of hashing the value once, do it multiple times. For example, this:
$hash = md5( md5( md5( $salt.$password ) ) ); is exponentially more secure than just hashing once.

you could even do something like
$hash = md5( $garlicsalt.md5( $seasalt.md5( $rocksalt.md5( $salt.$password ) ) ) );...of course, this sort of extreme measure is completely unnecessary in almost any code you or I are likely to write, but it's good to know.

(just don't forget how you did it)

also, some people might ask, "only 32 characters??? SOME values will have duplicate results!!!"

While logically true, no one has found duplicate values yet. And believe me, they're looking - everyone wants to the status of being The First.

But in the meantime, I look at it this way:


...A higher probability exists that every member of your programming team will be attacked and killed by wolves in unrelated incidents on the same night.

kuau
01-19-2012, 12:17 PM
I literally had this window open for 2 days writing a response and then when I submitted it, it told me I had to reload the page and saw all these subsequent entries, but I have to go running right now so I'll just submit what I had for now. Just ignore if you have since answered these questions...

Dear Adrian & Daniel: Thanks very much for all the answers. :)


The simplest solution to this would be to have all of your password-protected PHP pages in one (non-htpasswd) folder, and all your other restricted files in a different folder.

To me this implies that by having all the private files in one folder, I can protect the whole folder. I don't know how to do that except with htaccess (?). Maybe I am not understanding what you mean.

Did you find the code you use to clean user input? I would really appreciate having something an expert considers good protection against SQL injection because I'm not sure what the bad guys can do so am not sure how to protect against it. Thanks.

OK, now I understand about encrypting passwords. Figures... right after I perfected my script to send the forgotten password! :( I did find a script for generating random passcodes.

I remember you said this...

It might be best to make it so you can log in using $_GET, so you could just create a hyperlink in the email and the user can log in to edit with one click; something like http://example.com/edit.php?email=user@example.com&pass=73845ed8a4b8c9e9ff01276af9ce88e

I'm just not sure how to implement it. How do I log them in to change their password? Do I replace their password first with the generated one and then use it to log them in using GET? I feel as if I may be reinventing the wheel here. Are there some examples online of this process? I found this one but apparently it is not secure enough based on the comments...

http://www.danbriant.com/general/creating-php-password-reset-script/

As for magic quotes, if I turn it off in php.ini, I know it then causes problems if there are apostrophes in the text. Is addslashes($str) sufficient to do what magic quotes would have done, and if so, isn't that just as insecure as magic quotes?

If you start a session, how do you know what values it is tracking and how do you access them?

Thanks, e :)

djr33
01-19-2012, 07:30 PM
To me this implies that by having all the private files in one folder, I can protect the whole folder. I don't know how to do that except with htaccess (?). Maybe I am not understanding what you mean.Yes, use .htaccess to protect the files you don't want accessed. Use PHP just in PHP files to control access-- of course you don't want to actually block access entirely to PHP, so you'll have a password or user system or whatever. That's not really the same as .htaccess.
Actually, unless there's a reason you want to download your protected (non-PHP) files, I'd recommend against a password-- just block the folder entirely. You won't be able to access it either (except by FTP of course) and it will be completely safe. If they're blocked, I assume that means you're not using them except for server internal reasons. Note that PHP can still access them if you write that into the code. For example, you can have a "hidden/" directory containing "security.php" and include() the security.php file into other PHP files, even though via HTTP it would be blocked.


For MySQL injection, the single function mysql_real_escape_string() does everything you need. The only other issue is the outdated and troublesome magic_quotes situation. Just turn it off on your server and you don't need to worry about it. If it is on, you need to escape it, and I believe what you posted is fine. When traq posts his code, maybe that will be better (I'm not yet sure how), but for now I think what you have is ok, but not needed unless magic_quotes is on. On the other hand, if you want to write code that can be portable (installed easily on any server) then checking for that, even if it is off on your server, wouldn't hurt. But that's not important unless you're distributing your scripts to others (or using them for multiple clients and/or on multiple personal servers).


You should be able to find plenty of resources about "forgotten password scripts" if you search for that. In short, you will give them a code by email. When they get this code they can either click the URL directly (which includes the code) or type in the code in a form on your site. You can decide whether they need to have the username and/or email as well-- that's not technically required. This is a secondary login system and you will simply tell your server to let them bypass the normal system if they have this code. The way that I do it is by creating a new database table of forgotten password codes with two columns: a username/id and a code. Then when that code is entered, they get immediate access to change the password of that account. So of course you need the passwords to be difficult to guess (at least 8 characters and all that stuff). You might also want an expiration time so that a hacker doesn't get a year to guess what might have been sent to the email (that they can't see because they're not the user).


Magic_quotes is bad. You don't want to replace its behavior if you turn it off-- you want to get rid of it completely. You don't need to add slashes or do anything. Now, in some cases, magic_quotes is useful, but not in all cases. The problem is that it is inconsistent. So, if you turn it off then do everything yourself, it will be consistent and you never need to

djr33
01-19-2012, 07:30 PM
This is broken into a second post because the system wouldn't accept it as one. Not sure why, but maybe it was too long.
-------


Again, sessions are easy. There are two very simple steps:
1. Include the code to start a session at the top of every page.
2. Use $_SESSION['variable'] to access the session variable named "variable". Repeat.

It is tracking whatever values you've put it in. If you want to see what values it contains (for debugging/testing, not for public release) then use print_r($_SESSION); to see the entire array.
$_SESSION is an array just like anything else. It's a superglobal so you don't need to worry about scope (that is, you can use it inside functions or wherever and it's always the same and available). It's like $_GET and $_POST, except that you often write to it rather than just retrieving information from it. (You can put information into $_GET and $_POST too, but it's not often very useful.)

Anyway, here's an example:

<?php
session_start(); //session is active;
//this is the same session as any other pages visited recently
//you can't have multiple sessions or overlapping sessions
//sessions are either on or off and if there's too long a gap, then they reset

$_SESSION['variable'] = "value"; //store something
echo $_SESSION['variable']; //echo "value";

//now this works just like any other variable/array
//the only special part is that the same information is available on new pages
?>

<?php //imagine this is now a new page, 2.php, loaded 2 minutes later:
session_start();

echo $_SESSION['variable']; //magically, you get "value" again from that other page
?>

So again, sessions are incredibly easy-- in fact, they're probably the easiest thing in PHP in my opinion. Then again, once in a while you need to change the session length in the cookie or fix subdomain problems, but aside from configuring them overall, they really are easy to use.
But of course they appear confusing at first because they are counter-intuitive to the way that PHP usually works. Don't worry if you're confused-- just try them out and they'll make sense very quickly.
(In how they actually work, sessions are incredibly complicated, involving a temporary database on the server and other stuff. But PHP deals with all of that for you and you don't need to do anything at all.)

The one other thing you might want to do some time is destroy a session. This is often used to log users out or restart a process (a site-wide process, not just something on one page).

<?php
session_destroy(); //no more session; all of the variables are gone
//and you will need to start a new session if you want one
?>

traq
01-19-2012, 10:24 PM
To me this implies that by having all the private files in one folder, I can protect the whole folder. I don't know how to do that except with htaccess (?). Maybe I am not understanding what you mean.what Daniel said.

Did you find the code you use to clean user input? I would really appreciate having something an expert considers good protection against SQL injection because I'm not sure what the bad guys can do so am not sure how to protect against it. Thanks.
[...]
As for magic quotes, if I turn it off in php.ini, I know it then causes problems if there are apostrophes in the text. Is addslashes($str) sufficient to do what magic quotes would have done, and if so, isn't that just as insecure as magic quotes?

For MySQL injection, the single function mysql_real_escape_string() does everything you need.
[...]
On the other hand, if you want to write code that can be portable (installed easily on any server) then checking for that, even if it is off on your server, wouldn't hurt. But that's not important unless you're distributing your scripts to others (or using them for multiple clients and/or on multiple personal servers).
[...]
Magic_quotes is bad. You don't want to replace its behavior if you turn it off-- you want to get rid of it completely. You don't need to add slashes or do anything. Now, in some cases, magic_quotes is useful, but not in all cases. The problem is that it is inconsistent. So, if you turn it off then do everything yourself, it will be consistent and you never need to

That is the situation (portability) that I was referring to; but it beneficial even if you don't even plan to share your code: do it once and forget about it.

to recap:
1. You want to completely get rid of magic_quotes_gpc.
2. You can't effectively do that from inside your php script - only via server configuration.
3. You might not have access to your php.ini, and/or you might forget about it at some point.

This takes care of that for you: counteracts the affects of magic_quotes_gpc if it's turned on; does absolutely nothing if it's turned off.
// if get_magic_quotes_gpc is set in your config, kill it! KILL IT!

// (using ini_set('magic_quotes_runtime', 0); is useless:
// the evil slashing has already happened,
// and the setting is restored to its default next time a script runs.)
if(get_magic_quotes_gpc()){
// make strip_slashes() recursive, so it affects _all_ values in the GPC arrays
function stripslashes_recursive( $v ){
return is_array( $v )?
array_map( 'stripslashes_recursive',$v ):
stripslashes( $v );
}
// if you didn't know, GPC stands for GetPostCookie,
// so those are the superglobals you need to "fix":
$_GET = stripslashes_recursive( $_GET );
$_POST = stripslashes_recursive( $_POST );
$_COOKIE = stripslashes_recursive( $_COOKIE );
}
// I also do this
// ( $_REQUEST is unrelated to our magic_quotes problem, but evil nonetheless )
$_REQUEST = NULL;this solves your Magic Quotes problem, which un-complicates (does not solve) your SQL injection issues.

You must still use mysql_real_escape_string() (or switch to mysqli or PDO and use prepared statements ;)) to sanitize your user inputs - this is not intended to replace the need for that.



As for your question about "using $_GET" with your "forgot password" script:

when a user says they forgot their password, you might do something like this:

1. create a temporary password (something random and hard-to-guess)
2. store the temp password in a special table in your DB, along with the username and email it belongs to, and the time it was created
3. send the temp password to the user's email - BUT, instead of saying "here's your temp password," give them a link like this:

'<a href="http://example.com/lostpass.php?email='.$user_email.'&passonce='.$temp_password.'">click here to recover your password</a>
4. when they click on the link, you can check the user email against the temp password (and how long ago the password was created; it's good to make these expire within a day at most).

This way, recovering their password is as convenient as possible: just click the link and follow directions.
You might also give them the temp_password, so they can enter it manually, in case they have an objection to clicking on links in emails (if they just requested a new password, they ought to trust you; but it is a good security habit).

IF the temp password is valid:
1. log the user in (only for the session).
2. redirect them to the "change your password" page and tell them to change their password (good idea to make this _required_).
3. delete the temp password so it can not be used again.

REALISTICALLY, even though the reset-pass-via-email approach is widely used (even by google and amazon, among others), the concept is not fool-proof. It relies on two things that you can't be sure of:

1. the user's _current_ email address is in your records.
2. the user's email account has not been compromised.

However, this is all beyond your control, and responsibility for both issues rests squarely with the user.

djr33
01-20-2012, 02:18 AM
Traq, do you have any reasonable alternatives? Sure, the email account might be hacked and/or old, but is there any other way? Google now tries to use a mobile phone number for this as well, but that is similarly limited (what if you lose your phone or it is stolen?).

One more option is to include a "contact us" link near the forgotten password form to deal with weird situations. Assuming you can trust someone who claims they can't access their account, you can always help them manually.

traq
01-20-2012, 05:06 AM
Alternatives? Not really. The 'contact us' link is good, but you need to be careful - tricking a human into believing you are who you say you are -can- be easier than hacking the email account. It's been done. :)

About mobile phone numbers, etc., yes, it can provide a fallback method for verifying Id, but at the end of the day it's really just another point of failure.

There's no easy solution without sacrificing user-friendliness (which we're obviously not trying to do).

kuau
01-20-2012, 06:28 PM
Wow, you guys are an incredible wealth of information! Thank you!

My only real experience with magic quotes was a nightmare. I had just moved a new client's Webcalendar database from one host to another. The new host had magic quotes OFF so every time a user submitted an event or a name with an apostrophe in it, it was interpreted as a delimiter and threw a SQL error and refused to load the record. The owners were freaking out. I had to call the guy who originally installed the database and he told me to turn on magic quotes - end of problem.

I always have total control of the php.ini file, but I'm afraid to turn off magic quotes. Especially if there is no step taken to handle the delimiter problem, how can this possibly work? Wherever it caused a problem, I had to use addslashes to fix it.

Regarding sessions, this is one place I was hoping to use them... imagine an art gallery with 3 art consultants all using the same computer to input client info and sales. If they each login under their own login, can sessions keep track of who is who? Or on one computer there can be only one session at a time? Does a system restart end a session?

Thanks, e :)

djr33
01-20-2012, 06:46 PM
A session is unique to an individual connection based on the session_id. I guess technically two users could be sharing a session (in weird circumstances) if they had the same session_id, such as by "hijacking a session" by stealing the cookie from someone's computer. Or you could just intentionally give your id to a friend so you could have the same session. But that never happens accidentally.

In short, there's never information shared between users. Sessions don't replace databases or anything like that. If you need to communicate between multiple users, you'll need to use the other techniques you already know for that.


As for magic_quotes, yes, that's why it is "useful" and why it was created. But the problem is that it's like trying to fight a war with rocks (rather than guns)-- it can do the same thing, but often isn't as efficient or accurate. Relying on magic_quotes often leads to systems that miss something else that needs to be escaped and can cause the double escaping problem. So rather than finding a problem and fixing it with magic_quotes, I highly recommend that you fix it manually-- addslashes is one way. But realize that there are other things that may need to be escaped depending on how the data is being used.

Here's a quick list of escaping:
strings (for example, outputting Javascript): addslashes()
html: htmlspecialchars()
mysql: mysql_real_escape_string()
That's not a complete list.

traq
01-20-2012, 09:28 PM
which characters are unsafe varies depending on the database. mysql is different than oracle, is different than mssql, etc. (if you look at the documentation, you'll see that magic_quotes escapes ' " \ and NULL - a different list than mysql_real_escape_string()).

That's why you should be using database-specific functions, like mysql_real_escape_string() - but using both leads to the "double-escaping" problem.

Aside from that, not all submitted data is destined to be sent to the database anyway. Unnecessary backslashes can cause problems in other code. Consider this:
<form method="post">
<p>is your name <b>Adrian</b>?</p>
<input type="submit" name="submit" value="That's my name!">
<input type="submit" name="submit" value="No, it's not">
</form>
<?php
if( $_POST['submit'] == "That's my name!" ){ /* won't work if magic_quotes is on */ }
elseif( $_POST['submit'] == "No, it's not" ){ /* won't work either */ }

djr33
01-21-2012, 04:01 AM
I guess the short version of all of this is simple: escaping is always context dependent. You can't pre-escape everything because escaping by definition is within a certain situation (such as a string in PHP, a query in MySQL or HTML output), and escaping must be based on which characters are active for that context.
magic_quotes is therefore logically badly designed, and it will work, but only if it correctly guesses the potential future context for your use of the data. That's because magic_quotes is context independent.
The secondary problem is that some servers have it and others don't, so inconsistencies are common, and that might be the biggest source of the double escaping problem.

ayamkampung
01-23-2012, 03:00 AM
using htacess helps me a lot!

traq
01-23-2012, 03:06 AM
using htacess helps me a lot!

...helps you do what?
we aren't discussing any htaccess methods here.

if you're talking about turning off magic_quotes_gpc, you should be doing so in your php.ini file.

If that's not possible, then it's likely that you'd also have problems changing the setting via htaccess - but at that point, using a runtime script like the one I posted would be a better (more universally reliable) option anyway.

kuau
01-23-2012, 03:49 AM
OK, I'll turn off magic quotes in php.ini. Then the only way I can see of preventing errors from apostrophes in user input is to addslashes. For example, if lastname is "O'Brian"...

$_POST['lastname'] = addslashes($_POST['lastname'])

And, if I understand correctly, adding slashes accomplishes exactly the same thing as if magic quotes were on. So someone could still use SQL injection unless I use mysql_real_escape_string(), yes? I understand how double escaping can happen but have never had a problem.

So are you saying the very best solution that covers all contingencies is to:
1. Turn of magic quotes in php.ini
2. Use addslashes for user input form fields
3. use mysql_real_escape_string() before loading to database

So I would end up with something like this??...


$lastname = mysql_real_escape_string(addslashes([$_POST['lastname']))

djr33
01-23-2012, 06:29 AM
There's no need to use addslashes() here. addslashes is a function for escaping only in a context where those characters as defined by addslashes() need to be escaped. That's not the escaping function for mysql: the escaping function for mysql is only mysql_real_escape_string(). Any direct user input can be put through that single function and then is safe.

There are cases where you should use addslashes, although honestly very few. Use it when you're looking specifically to fix just the quotes, not any other control characters. For example, if you're creating a string for PHP. If you want to dynamically create a .php file, then you can write the following code to that file (as the contents of that file):

$myvar = addslashes($_POST['myvar']);
$contents = '<?php $myvar = "'.$myvar.'"; ?>';
fwrite($file,$contents);
The same would apply if you were outputting Javascript strings (the text to be assigned to a variable, generated within PHP).
But these situations aren't very common. The most common cases of escaping are mysql_real_escape_string() for MySQL and htmlentities() for HTML.


The double escaping would happen if you used addslashes() when magic_quotes is on.

(Technically, as far as I know, mysql_real_escape_string() won't ever result in double escaping because its' a 'smarter' function than addslashes()-- it's designed to make data safe, rather than just logically adding slashes to certain characters.)

traq
01-23-2012, 07:15 AM
1 & 3.

Whatever you put into MySQL_real_escape_string() will come out ready to be treated as literal data by MySQL. Use it - no other functions.

Addslashes() is not suitable for this purpose.

kuau
01-23-2012, 08:01 PM
So are you saying that MySQL_real_escape_string() would take malicious code and render it inert by turning it into a literal?

So you might find something in your database like:

Lastname: DELETE FROM clients; DROP table clients;

Currently I have magic quotes ON and if I don't add this bit of code:


$clientname = addslashes($client['lastname'].", ".$client['firstname']);

the data will not load to the database for names like O'Reilly, O'Brian, etc. Are you saying it would be better for me to use this? ie. it serves both functions at once?


$clientname = MySQL_real_escape_string($client['lastname'].", ".$client['firstname']);

Thanks

traq
01-23-2012, 09:37 PM
all lowercase (my tablet was auto-capitalizing, sorry)

and, it is important to remember that literal stings still need to be quoted 'like this' for SQL.

<?php
$lastname = mysql_real_escape_string( $_POST['lastname'] );

$SQL = "SELECT * FROM clients WHERE latsname = '$lastname'";

// say $_POST['lastname'] was "O'Brien"
// mysql_real_escape_string() will change it to "O\'Brien"
// so when you insert it into your query, you'll get:
// "SELECT * FROM client WHERE lastname = 'O\'Brien'"
// which will insert correctly.

// say $_POST['firstname'] was "DELETE FROM clients"
// mysql_real_escape_string() won't do anything to this string,
// but since the string is put into single quotes in your query, it will be treated as literal data:
// "SELECT * FROM client WHERE lastname = 'DELETE FROM clients'"
// probably won't get any results, but it won't hurt anything.