3

Question 1 : Can I just use $userid = mysql_real_escape_string($_GET['user_id']);

Or I need to use the codes below is better?

function mysql_prep( $value ){
        $magic_quotes_active = get_magic_quotes_gpc();
        $new_enough_php = function_exists( "mysql_real_escape_string" ); //example. php >= v4.3.0
        if( $new_enough_php ) { //php v4.30 or higher, undo any magic quote effects so mysql_real_escape_string can do the work
            if( $magic_quotes_active ) { $value = stripslashes( $value );}
            $value = mysql_real_escape_string( $value );
        } else { //before php v4.3.0.
            if( !$magic_quotes_active ) { $value = addslashes( $value ); }
        }
        return $value;
    }

$userid = trim(mysql_prep($_GET['user_id']));

Question 2 : Do we really need to use md5() or shal() on the $_SESSION['user_id']? Why we need that? session hijacker can get the session id only, but he cannot get the session variable value right? If so, then I don't need to hash the value of $_SESSION['user_id'] anymore right? For example :

if (isset($_POST['login'])) {
        if ($username==$user_username_in_db && $hashed_password==$user_password_in_db) {
                $_SESSION['user_id'] = sha1($user_id_in_db); //sha1 convert userid to crazy long characters
        }
}

$query2 = "SELECT id FROM user WHERE sha1(id)='{$userid}' LIMIT 1";

Question 3 : Since php session hijacking happen and I can't afford to use ssl/https, so I make the website request the user to submit password everytime they try to delete a message or friend, because the session hijacker may impersonate the user to delete his messages/friends. May I know is it dangerous if my website always ask user to input password? The password will be easier to be hacked? May I know session hijacker can only impersonate the user, but cannot steal the user's password right?

zac1987
  • 2,721
  • 9
  • 45
  • 61
  • 1
    mysql_real_escape_string was added in PHP 4.3.0. If your version doesn't have it, you have FAR bigger problems... – ircmaxell Apr 26 '11 at 15:46
  • 2
    Also, Partial duplicates of 1.) [Are dynamic queries safe](http://stackoverflow.com/q/4771984/338665), 2.) [Differences between hashing and encryption](http://stackoverflow.com/q/4948322/338665) and 3.) [Session Fixation / Hijacking](http://stackoverflow.com/q/5081025/338665) – ircmaxell Apr 26 '11 at 15:51
  • WOW, thanks for your links!!! SQL injection attack is possible with any character encoding where there is a valid multi-byte character that ends in 0x5c. May I know latin1_swedish_ci is multi-bye character that ends in 0x5c? How to check it? And Is it possible the SQL injecter change latin1_swedish_ci to GBK ? – zac1987 Apr 27 '11 at 09:38

4 Answers4

8

Question 1: if your user_id is stored as an integer in the database, you can use:

$user_id = intval($_GET['user_id']);

So if someone tampers with the query string, all that can happen is that they get a blank result. However, it's unclear HOW you use that $_GET['user_id'];

Question 2: sha1 and md5 are hashing algorithms. That means that for any given string of any length, they give back a number that's displayed as 41/32 byte hex string.

What's the use of that? The use is that those algorithms aren't reversible, which makes them perfect for hiding information such as someone's username and password. Many people use one and the same password for everything, in order to ensure their password wont' get stolen in case you messed up and a hacker got the access to your database - you provided another level of security for your users - no one should be able to get an actual password out of the hash. Naturally, that also prevents the person who has the access to the db to read people's passwords and compromise their privacy. Now, there are ways to try to reverse hashes to plain text (so called rainbow tables) but that's another topic all together.

Question 3: you should actually prevent session hijacking in the first place. Why does it happen? Are you exposing session_id to the public somehow (via URL) and are you implementing standard checks?

Asking for password every now and then is an annoyance to the user and should be avoided, unless you can't think of a way to protect the session.

As for other things, there's something called PHP PDO which SHOULD in theory make the use of cleaning strings, connecting to the database and inserting stuff into the database much easier (although it's quite complex compared to regular mysql_ or mysqli_ functions so people seem to avoid it). You should at least read about it to get an insight on what it does and how it can help you against SQL injections.

Michael J.V.
  • 5,499
  • 1
  • 20
  • 16
  • 1
    Re question 3 - there are cases of session hijacking that are impossible to protect against without https. Even Stack Overflow has the same issue. http://meta.stackexchange.com/questions/69171/why-doesnt-the-stack-overflow-team-fix-the-firesheep-style-cookie-theft – Pekka Apr 26 '11 at 15:50
  • You might want to hash the user id to avoid guessing of the other users URL in case the user ID appears there. You can't try 1,2,3, and so on. Makes sense for sensible data (like pictures, when some pictures are private, for example) but if the other URLs are public, google will also list them all. – Capsule Apr 26 '11 at 15:56
  • 1
    @Capsule - since the context of how $_GET['user_id'] is used is not mentioned, it's hard to assume what's useful. For example, if the user is logged on, is it necessary to hide user_id in the query string if the logged on user is attempting to send a message to his friends? I agree, in some cases it's good to obfuscate the actual user_id, as for how - that's another topic for itself. @Pekka - yes, on an **open wireless** network it's easy to obtain someone's cookie which makes session hijacking trivial without HTTPS. – Michael J.V. Apr 26 '11 at 16:01
  • @Michael, thanks for your answer. I store username on php session after the user login his account. I read a lot of article about how to prevent session hijacking and I realize there is no way to prevent it except https. – zac1987 Apr 26 '11 at 16:21
  • @Michael J.V, OMG I never knew there are ways to reverse hashes to plain text, I will search more info about rainbow tables, thank you. – zac1987 Apr 26 '11 at 16:38
  • @zac1987 in securing your site it won't help you a bit though. – Your Common Sense Apr 26 '11 at 16:50
  • @Col. Shrapnel, do you mean I should not waste my time to study about rainbow tables? I guess after I study about rainbow tables, I still won't get any solution to avoid the rainbow tables thingy...I guess it is impossible to protect hacker to hack the password, just let it be~ – zac1987 Apr 26 '11 at 16:57
  • 1
    @zac it always worth to learn something. However, I'd prefer something more practical and, er, systematic. There are thousands wonderful things about password hashing: rainbow tables, salts, brute force, dictionary attacks and so on. But it won't help you in securing your site. – Your Common Sense Apr 26 '11 at 17:10
1

Question 1 : Can I just use $userid = mysql_real_escape_string($_GET['user_id']);

yes and no.
yes because you don't need all that code below.

no because mysql_real_escape_string has nothing to do with security.
it doesn't make data "safe", nor "eliminate injections", nor "convert dangerous characters".
but just merely escape string delimiters.
that's all.
So.

  • unless you're going to use string delimiters (quotes) around your data, it's entirely useless.
  • every time you're going to put some quote-delimited data into query, you should use this function. NO MATTER if your data is safe or not, came from user, server or whatever source - it's all irrelevant. mysql_real_escape_string belongs to quoted data and nothing else.
  • still there is some nitpicking about encodings, so, if you're gonna use it, you should always set your encoding using mysql_set_charset() function.
  • you can use prepared statements instead of putting your data directly into string.

  • (surprise!) SQL security is not limited to this function usage. there are numerous other issues.

  • overall site security is not limited to SQL injections and session hijacking.
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
0

You should never save your password in plain text. You better use MD5 or SHA1. The advantage of using one o those is that no one can "decrypt" the password it is a just "one-way" encryption.

PachinSV
  • 3,680
  • 2
  • 29
  • 41
  • 1
    Actually, it's not encryption but hashing. Encryption assumes it's a two-way process, whereas hashing isn't. – Michael J.V. Apr 26 '11 at 15:48
  • Actually md5 can be reversed engineered, `md5(salt1+pass+salt2)` bit better – Pablo Apr 26 '11 at 16:00
  • 1
    @Pablo MD5 cannot be reverse engineered. It can be looked up via a rainbow table, but that's quite different from reverse engineering. See [this question](http://stackoverflow.com/q/3049070/338665) for more info. – ircmaxell Apr 26 '11 at 16:02
  • @ircmaxell right, the method turns out to be efficient anyhow – Pablo Apr 26 '11 at 16:16
0

Always use bind parameters instead of escaping to prevent SQL injection attacks. Escaping can work, but it's error-prone: different databases have different escaping rules, and you might inadvertently escape based on the wrong set of rules, leaving gaps that can be exploited. If you keep the parameter values separate from the query string, there's no chance that a malicious parameter value can change the structure of the query. PHP data objects are the right way to do this in PHP.

I don't see a point in hashing the user ID stored in the session. The usual reason for hashing something is to prevent someone who sees the hash from knowing what the "original" value was, but things stored in $_SESSION aren't shown to the user anyway. If you were using register_globals, it could potentially be a defense against someone fooling code that refers to $user_id by putting a user_id parameter in the query string, but that can be circumvented (the attacker can just put the hash of the target user_id in their query parameter), and you shouldn't be using register_globals anyway (for exactly these reasons).

Asking the user to enter their password more frequently means the password has to be transmitted over the network more frequently. Since you're not using SSL, that means there's an increased risk of it being eavesdropped. There are other ways to avoid session hijacking, such as storing the user's IP address in the session and discarding the session if a request with that session ID comes from a different IP.

You can also implement support for OpenID as an alternative to password authentication. If you do use passwords, you should store only salted hashes in your database, so that if someone manages to get a copy of your passwords table, they can't recover the users' actual passwords.

Wyzard
  • 33,849
  • 3
  • 67
  • 87
  • @Wyzard, some people said better don't avoid session hijacking by ip address, because AOL keep renew user's ip address when the user visit different pages. Info at http://stackoverflow.com/questions/477649/can-we-hack-a-site-that-just-stores-the-username-as-a-session-variable . Furthermore must not avoid session hijacking by user-agent because some people like to use two browsers at the same time. – zac1987 Apr 26 '11 at 16:29
  • @zac1987, Those are true, and I'm glad you've considered them. My main point is that there are a variety of techniques that can be used to combat session hijacking without having to ask the user to manually re-authenticate. Another option is to change the session ID after a successful login, to prevent session fixation attacks. – Wyzard Apr 26 '11 at 16:35
  • @Wyzard, from what I know, at beginning the user computer/browser doesn't have the session ID (cookies). The session ID is send to the user computer/browser only when the user successful login to his account. The user cannot login two times without logout for the 1st time. If use logout, the session will be destroyed by this code session_destroy(); then when the user login again, sure it will assign another session id right? Is this what you mean by "change the session ID after a successful login" ? – zac1987 Apr 26 '11 at 16:46
  • @Wyzard, may I know what do you mean by "bind parameters"? How to do that? Can you give me some example? – zac1987 Apr 26 '11 at 16:53
  • Update my question 2 : Do we really need to use md5() or shal() on the $_SESSION['user_id']? Why we need that? The session hijacker can get the session id only, but he cannot get the session variable value right? If so, then I don't need to hash the value of $_SESSION['user_id'] anymore right? – zac1987 Apr 26 '11 at 18:38
  • @zac1987 the might not *normally* have a session ID before they log in, but they may if they're the target of a [session fixation](http://en.wikipedia.org/wiki/Session_fixation) attack. If a user comes in with a fixated session ID that an attacker knows, and then logs in, the attacker knows the ID of a logged-in session. If you change the session ID upon login, the attacker won't know the ID of the logged-in one. – Wyzard Apr 27 '11 at 02:15
  • @zac1987 To use SQL bind parameters, you put question marks in the query string in the places where the parameters belong, and then you call separate functions to specify the values of the parameters. In the case of PDO, you'd typically use `PDOStatement->bindValue()`. Since the parameter value isn't part of the query string, it can't change the structure of the query string. – Wyzard Apr 27 '11 at 02:19