Randomization, Obfuscation, and Cryptography in PHP

Simple Techniques to Lock Down your Website

Tutorial Details
  • Topic: PHP
  • Difficulty: Intermediate
  • Estimated Completion Time: 45 minutes

One crucial part of PHP development practice is always keeping in mind that security is not something you can simply buy off the shelf at your local convenient store. Ensuring the security of your web applications is a process, which over time, needs to be constantly evaluated, monitored, and hardened.


Introduction

While the use of filters and validating data is one part of the security process, a web developer should be aware that Randomization, Obfuscation, and Cryptography in PHP can make a difference in the security of web applications. This tutorial will guide you through some simple techniques at creating and using random or unique values within your web applications, taking a look and applying some general obfuscation techniques, and looking deeper into the science of Cryptology and it’s use within PHP.


What you Will Learn

  • How to generate random values with PHP
  • Generating random Passwords
  • Salting Passwords and Authenticating The User
  • Obfuscation in PHP, an Overview
  • Cryptography in PHP and it’s Applications

Generating Random Values

Dictionary.com defines randomization as:

“-verb: to order or select in a random manner, as in a sample or experiment, especially in order to reduce bias and interference caused by irrelevant variables; make random.”

Random number generation is determined in a variety of ways, however computational generators fall short of ‘true’ randomness as seen in nature or electronic noise(the fuzzy, screeching, black and white channel on TV). These computed values are regarded as pseudo-random.

PHP provides us with a couple of different ways to create random values. Let’s look at a few of the more popular functions.

<?php
rand(int $min, int $max);
mt_rand(int $min, int $max);
str_shuffle($str);
uniqid($prefix, more_entropy=);
?>

The two functions rand() and mt_rand() are likely the most widely used functions to generate a set of random numbers in PHP. The function rand(); is an older generator, and is falling out of use due to mt_rand(); which is faster, more reliable, and can handle a higher maximum integer value on some platforms. The function str_shuffle() does exactly what you would expect it to, it shuffles a string passed to it.

<?php
//Examples of mt_rand() usage
print mt_rand();//default
	
		echo "<br />";
	
print mt_rand(0, 20);//Outputs a random integer between 0 and 20
	
		echo "<br />";
	
//Examples of rand() usage
	
print rand();//default
	
		echo "<br />";
	
print rand(0, 25);//Outputs a random integer between 0 and 25

		echo "<br />";
	
//Example of str_shuffle usage
	
$string = 'abcefghijklmnopqrstuvwxyz';
	
print str_shuffle($string);//shuffles $string
?>

The rand() and mt_rand() functions both accept two parameters where $min is the lowest integer to start with, and $max being the largest integer to end with. The function str_shuffle takes one parameter, a string, outputting a shuffled mutation of the string. It acts the same as if you were shuffling a deck of cards.

While mt_rand(); will spit out a random integer, and str_shuffle will mix a string up, a function widely used to create random unique values is uniqid(). This generates a prefixed unique identifier based on the current time in microseconds(via php.net). Using this function is useful for creating session tokens and even form keys as seen in Secure Your Forms with Form Keys.

<?php
//Examples of uniqid() usage
	
print uniqid();//default
	
		echo "<br />";
	
print uniqid("NETTUTS", TRUE);//Adding an additional prefix and setting more_entropy to TRUE
?>

The function uniqid() accepts two parameters the first appends a prefix to the results while the second, if set to TRUE, will add additional entropy to the end of the returned value.


Generating Random Passwords

There are a gazillion examples on the web which generate random passwords, all do a fine job at it. “But why,” you ask “would I need to generate a random password?” Well the answer, quite simply, is so you do not have to rely on the end user to provide themselves with a less than secure password at the get go. Generating random passwords is very useful in user registrations, or when a user makes a request because they have forgotten their password. Doing this ensures a strong password at the beginning of a users experience at your website, or can cut down lines of code when a user needs to gain access again.

Let’s look at some examples:Example 1

<?php

//A simple function which will output a random password
function randompassword($count){

$pass = str_shuffle('abcefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890@#%$*');

return substr($pass,3,$count);//returns the password

}
?>

This example shuffles a string with str_shuffle and will return a string within a counted range. So if you wanted to generate an 8 character password then you would pass 8 to the function randompassword, or randompassword(8) from your source code.

Example 2

<?php

//Another example to create a random password
function anorandpass($count) {
	
	$m_rand = mt_rand(); //generate a random integer

	$u_id = uniqid("MNO!@#$%^&*=+XYZ", TRUE);//create a unique identifier with some extra prefix and extra entropy
	
	$combine = $m_rand . $u_id;// Combine the variables to form a string
	
	$new = str_shuffle($combine);//shuffle our string
			
	return substr($new, 2, $count);//return the password
}
	
print anorandpass(8);

?>

In comparison, example one takes a static string and mixes it up then returns it, example two adds in more dynamic flavor(mmm tasty). In example two the string being shuffled is no longer static, but changes with each generation. While the first example is certainly sufficient in most cases to generate a strong password, the second example allows us to ensure the string length and characters will change with use, greatly decreasing the chance of a duplication.

Enforcing the use of strong passwords within a web application will deter users from visiting or signing up for a website. It is often a trade off between getting the traffic you desire, and ensuring the security of the application. I suggest allowing your users to create their own passwords at sign-up, or allow them to choose between the two.


Please Pass the Salt. Salting Passwords for Increased Security.

Salting passwords is an effective way to increase the security of your users accounts even if an attacker gains access to your database, if done right. It can be argued that, with access to the salt, an attacker can still gain your credentials. While this is true, applying some randomization techniques to the storage of passwords will make that process extremely difficult, especially if the storage of user information and content are divided into separate databases.


Why and How?

Again this falls under the “non-reliance of the end-user to provide themselves simple security” measure. Users generally use passwords which are easy to remember, and even use the same passwords across multiple websites(I know, right!?). Easy to remember passwords are generally words found in a dictionary and other kinds of values(ex. 12345, QWERTY). As developers we often scoff at this practice, but we cannot deny that it’s just the way things are.

In order for a web application to utilize a salt in a password, the application has to store it somewhere. It’s not recommended to use the same salt across an entire database of passwords, but to generate a unique salt per user. Generating one salt for an entire database actually decreases the security of the web application in a sense that if an attacker manages to crack it the entire scheme is broke, or if lost, renders the database useless. Creating a full fledged member registration system with all the bells and whistles is out of the scope of this tutorial, however we will be creating a simple system to use an example. Let’s look at generating a salt and applying some randomization techniques:


1. The Database Connection

Here is the SQL table that we will be using.

CREATE TABLE IF NOT EXISTS `users` (
  `usr_id` int(11) NOT NULL AUTO_INCREMENT,
  `usr_name` varchar(24) NOT NULL,
  `usr_pass` varchar(32) NOT NULL,
  `usr_email` varchar(255) NOT NULL,
  `usr_salt` varchar(255) NOT NULL,
  PRIMARY KEY (`usr_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;
<?php
/*db_config.php*/

//database configuration
$db_host ="localhost" ; //will likely stay the same
$db_name = "thedbname"; //the name of the database table
$db_usr = "username"; //your database username
$db_pass = "password";//your database password

//Establish a connection with MySQL and select the database to use
mysql_connect($db_host, $db_usr, $db_pass) or die("MySQL Error: " . mysql_error());
mysql_select_db($db_name) or die("MySQL Error: " . mysql_error());
?>

2. The Registration File

<?php
/*registration.php*/

//require our db_config.php file
require ('db_config.php');

//Check to see if the form has been submitted
if(!empty($_POST['username'])  && !empty($_POST['email']) && !empty($_POST['password'])) {
	
    //Escape our posted inputs
	$username = mysql_real_escape_string($_POST['username']);
	$email = mysql_real_escape_string($_POST['email']);
	$password = mysql_real_escape_string($_POST['password']);
	
    //generate a strong unique salt
	$salt_gen = uniqid(mt_rand());
	
    //Combine email, the password and the salt together
	$combine = $email . $password . $salt_gen;
	
    //md5 hash the combined password * Note: md5 is only used in this scenario as an example
	$newpassword = md5($combine);
	
    //insert the values into the database
	$registerquery = mysql_query("INSERT INTO users (usr_name, usr_pass, usr_email,  usr_salt) VALUES ('".$username."', '".$newpassword."', '".$email."', '".$salt_gen."')") or die("MySQL Error: ".mysql_error());
	
    //let the user know of success or failure
	if ($registerquery) {
		echo '<h1>Success</h1>';
	} else {
		echo '<h1>Failure</h1>';
	}
}
?>

Let’s go over the PHP code. To keep things simple we include our database config file. Next PHP checks to see if the form HTML has been submitted by checking if the $_POST variables are not empty. If they are not empty then the script proceeds to escape the posted form data from the user, preparing it to be inserted into the database. We then generate a simple salt using uniqid() and mt_rand() and storing it in the variable $salt_gen. To salt our password we combine the $password, then the salt. Next step, one way hashing the combined variables with md5.

“But wait! You also added the users email to the front of the password and salt combo!” Yup! I did this because, if an attacker gains access to my database in some way, and the salt, the only way the attacker is going to know for sure that the email address is used in the hashing of the password is if they have access to the source code. How random and unique is an email address?

To top the rest of the PHP code off we insert our variables into the database table within their respective fields, and give the user some feedback on success or failure. Now onto the rest of the registration file, the HTML

<!DOCTYPE html>
<html>

<head>

</head>

<body>

<form action="" method="post">
	<label for="username">Enter a Username</label>
    <input type="text" name="username" /><br />
    
    <label for="email">Enter your Email</label>
    <input type="text" name="email" /><br />
    
    <label for="password">Enter a Password</label>
    <input type="password" name="password" /><br />
    
    <input type="submit" name="submit" value="Submit" />
</form>

</body>

</html>

Here we create a simple HTML form which will collect a username, an email, and a password from a user. Nothing fancy here.


3. Authenticating the User

So we now have a simple registration form, which inserts a user into the database along with their salted password. Let’s create a login page which will require us to retrieve information from the database and authenticate the user. First the PHP:

<?php
/*login.php*/

//require our db_config.php file
require ('db_config.php');

//Check to see if the form has been submitted
if(!empty($_POST['username'])  && !empty($_POST['password'])) {
	
	//Escape our posted inputs 
	$username = mysql_real_escape_string($_POST['username']);		
	$password = mysql_real_escape_string($_POST['password']);
	
	//Grab the row associated with the username from the form
	$grab_row = mysql_query("SELECT * FROM users WHERE usr_name = '".$username."'") or die ("MySQL Error: ".mysql_error());
	
	//If only one row was retrieved
	if (mysql_num_rows($grab_row) == 1) {
		
		//create an array from the row fields
		$row = mysql_fetch_array($grab_row);
		
		//store the users salt in a var
		$salt = $row['usr_salt'];
		
		//store the users email in a var
		$email = $row['usr_email'];
		
		//recombine the variables email, password, and the salt
		$combine = $email . $password . $salt;
		
		//re-hash the combined variables Note:md5 is only used in this scenario as an example
		$auth_pass = md5($combine);
		
		//check the database again for the row associated with the username and the rehashed password
		$checklogin = mysql_query("SELECT * FROM users WHERE usr_name = '".$username."' AND usr_pass = '".$auth_pass."'") or die("MySQL Error: ".mysql_error());
		
		//if only one row is retrieved output success or failure to the user
		if(mysql_num_rows($checklogin) == 1) {
			echo '<h1>Yippie, we are authenticated!</h1>';
		} else {
			echo '<h1>Oh no, we are not authenticated!</h1>';
		}
	} else {
		echo '<h1>Oh no, we are not in the database!</h1>';
	}
}
?>

Basically what we are doing in the login.php file is taking the submitted form variables, grabbing the table row associated with the username and rebuilding the password from the elements in the database it was created with (email, pass, salt) and rehashing them. We then check the database again for the username AND the rehashed password value to find a match, outputting the user on success or failure. Finally here is the HTML:

<!DOCTYPE html>
<html>
<head>

</head>

<body>
<form action="" method="post">
	<label for="username">Enter your Username</label>
    <input type="text" name="username" /><br />
     
    <label for="password">Enter a Password<label>
    <input type="password" name="password" /><br />
    
    <input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Obfuscation in PHP

A simple yet complex definition of obfuscation is (use the version contained in the source if you wish to run the code):

<?php $a1c0_z2='c'.$a91.'tion ';$a91="a";$vly_ti="us".'ed';$j1h_32_a=' to';$z1b_1=$a91." ";$lz32i_4="“O"."bfus";$g1k0p='que ';$lv83="t".'ec'.'hni';$lFa='i'.'s ';if($z1b_1==$a91." ")$rx_b_1='a';$glccUv=" complic".$rx_b_1.'te ';$xl1ttf='code ';$zljal1="in such a";if($z1b_1==$a91." ")$s1b_1='a';$p1x2 =" w".$s1b_1."y ";$il_7x=' '.$b1zE_.'t i'.$l1yes;$b1zE_="i";$l1yes="s";$nltotry_ws='st'.$s1b_1."n";$yl5B_='thαt ';$dlno=' not ';$m1tomanythings="under";if($s1b_1=='a')$bz_1=$s1b_1;$Ozaq="d".$bz_1."ble"";echo base64_decode("JiM4MjIwO09iZnVzY3Rpb24mIzgyMDE7aXMmIzgyMDE7YSYjODIwMTt0ZWNobmlxdWUmIzgyMDE7dXNlZCYjODIwMTt0byYjODIwMWNvbXBsaWNhdGUmIzgyMDE7Y29kZSYjODIwMTtpbiYjODIwMTtzdWNoJiM4MjAxO2EmIzgyMDE7d2F5JiM4MjAxO3RoJmFscGhhO3QmIzgyMDE7aSYjODIwMTt0JiM4MjAxO2kmIzgyMDE7bm90JiM4MjAxO3VuZGVyc3RhbmRhYmxlJnF1b3Q7");?>

As you can see, this code is not meant to be distinguishable. There are no distinct variable names, there are no comments, no spacing, no indentation, no distinct order and it’s all in one line. Even though we cannot distinquish the code, our machines still know what it is. It works. This one line of chaos simply echos “Obfusction is a technique used to complicate code in such a way that i t i not understandable.” Yes, I know about the errors.

Obfuscation has pros and cons. It’s purpose is to disuade a person from finding out what code is doing at a glance, or for a period of time. This is a plus toward individuals with little to no knowledge of the programming language. However, anybody who has a basic understanding of PHP can disseminate the above obfuscated code and figure out what it’s doing, it might just take a little time. This is one of the flaws of obfuscation, it is not a form of encryption, it’s just an attempt to be cryptic. Obfuscation also normally adds to filesize. A lot of the time, you’ll encounter obfuscated code in propriatary and malicious software.


So How Can I Obfuscate My Code?

This is a common question. There are primarily two ways to obfuscate your code. First, you can do it by hand. Writing obfuscated code takes a long time. The example used in this article took a while to write because of the same reasons you use obfuscation in the first place (lack of structure, order etc…), this even resulted in some menial errors which I didn’t even want to hunt down and fix. The second way you can obfuscate your code is by buying software that does it for you. Using a program to obfuscate code is trivial, and of course costs money a lot of the time. Some software which claims to obfuscate your code, actually encrypts and/or encodes it in such a way it relies on a handshake to function. Often you’ll find software whose vendor won’t even guarantee your code will work when it’s done. Even in the example, I used a simple Base64 function to encode the construction of the script output.


Some Obfuscation Tips

  • Always, always, keep a clean version of the source for yourself.
  • The more random your technique, the better.
  • Eliminate all whitespace, where it is not needed.
  • Character Encode printed/echo’ed characters and spaces (i.e. quotations, thin spaces, apostropes, hypens)
  • The more complex the code, the better.
  • Disregard structure unless it is detrimental to the operation of the code(e.x. variable locations before they’re called)
  • Do not use distinguishable variable names, namespaces, or class names.
  • The less code you reuse, the better
  • Don’t believe it’s foolproof

To Obfuscate or Not to Obfuscate?

It really depends on your plan. Particularly if your looking to sell your PHP script (or any software) you need to license it. This is going to be one of the front line defenses to thwart the softwares intended audience from doing whatever they want. A prime example of licensing can be seen in the Envato Marketplace Wiki. However, you may want to obfuscate some, or all of your code for whatever reason. However due to obfuscations negatives, if your really that worried about the security of your source code, it may be worth looking to encryption instead.


Cryptography in PHP

Wikipedia.com defines cryptography as:

“the practice and study of hiding information.”

Cryptography is a big deal, wether your aware of it or not. In almost every web application presently deployed there is some presence of cryptography being utilized (i.e. mail clients and websites). As developers we need to be informed and aware of the practical applications of cryptography within our software. PHP provides us with some very fundamental and practical functions we can utilize to encrypt data. In this section, I will be mainly going over one-way hashing algorithms though I will touch lightly on Symmetric-key based encryption. There are plenty more (i.e. Steganography, Asymmetric-Key to name a couple).


The One Way Hash

Alot of the time we utilize one-way hashing as a way to securely store passwords and check the data integrity of files. While we do this, to authenticate members of a web application we hash the users entered password, and match it against the users stored hash. The same technique applies to checking the integrity of files.

SHA-1, 2, and 3

The SHA family of hash algorithms are currently the most popular, significantly SHA-1. Even though the SHA-1 algorithm may have a weakness, it is still in wide use.

<?php

///One way hashing with SHA-1

$string = "Netuts is Awesome";

$hash = sha1($string);
//or
$hash2 = hash('sha1', $string);

echo $hash."<br />";
echo $hash2."<br /><br />";

//Will output: 42d2f15c3f92d28d7d58776e5d81b800f662cc6c 
?>

In PHP, SHA-2 is called upon in a different respect, and requires PHP 5 greater than or equal to 5.1.2. SHA-2 is superior to SHA-1 and can be called with different bit sizes.

<?php
$string_sha256 = "Nettuts is Awesome";
$string_sha384 = "Nettuts is Awesome";
$string_sha512 = "Nettuts is Awesome";

$hash_sha256 = hash('sha256', $string_sha256);
$hash_sha384 = hash('sha384', $string_sha384);
$hash_sha512 = hash('sha512', $string_sha512);

echo $hash_sha256."<br />";
echo $hash_sha384."<br />";
echo $hash_sha512."<br />";

/* Outputs repspectively:
sha256 : 09074adc0d70e15b88494643e29c2836e1ab94a21989691dec594cb0bd742ebc
sha384 : 8535470750df54a78701d4bfe0451f9799057a5bc101944a32480d2436e8b95440bce3bcab3f9ce107b0b92d9595ae32
sha512 : c2e6dce873a71800b862791e56b480b976bb26cd3136c02da510c3905caa49b7b9e9260549976e1e741cc93e4569a611f2030d3b7104c6c6c2ff9e6c9bf0946a
*/

?>

The hash function is called by hash(algorithm, string); In the newest PHP versions the hash() function can be used to call any one-way hash algorithm PHP supports (i.e. md5, sha-1, haval, ghost). If you want to see a list of all the registered hashing algorithms you can use:

<?php
//As of PHP5 >= 5.1.2
print_r(hash_algos());
?>

SHA-3 is still being developed and considered for standardization. A competition to find a good candidate to act as the new secure hash algorithm was launched by the National Institute of Standards and Technology and entries for the competition were deadlined for October 31, 2008. A rather popular entry named Skein, has an available PHP module you can download (though you have to compile it yourself). Skein is developed by some big names found within the security industry such as Bruce Schneier, Niels Ferguson, and Stefan Lucks to name a few. The official Skein website can be found here.


Key-based Encryption

Symmetric-Key encryption methods is where the security of the encryption primarily resides within a key, which is shared between two points, where the data is encrypted and where the data is decrypted. A very good example of how this can work was provided by Christian Beikov’s “Creating a Crypter Class with PHP” tutorial.


HMAC

Essentially HMAC is like a mix between one-way hashing and key based encryption. HMAC security relies on the key size used, and strength of the hash function it is calculated with. You can somewhat compare this method to salting passwords.

<?php
$string_hmac = "Nettuts is Awesome";

//hash_hmac(algorithm, string to hash, key)
$hmac = hash_hmac('sha1', $string_hmac, 'secret');

echo $hmac."<br />";
?>

Wrapping it All Up

Well what a journey! Randomizing values, generating random passwords, salting, storing and authenticating users, obfuscation, crypto…seems like alot to take in. But worth it! It’s important to know what kind of security your going to implement into your web applications, and how your going to protect it. Even more, it’s important to keep a clever attitude towards these implementations and not think that security is only implemented by a few methods, but by a combination of them, with a dash of creativity.

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://andrew.chalkley.org Andrew Chalkley

    My pro tip:

    You could secure a website by taking it off the internet.

    • http://www.voveris.eu/ Faifas

      I couldn’t offer a better solution.

    • http://3twentythree.com Hayden

      That would also defeat the purpose of having a web site.

      The correct way to say that and the purpose in it is to say “The only absolute way to secure a server is to unplug it”. The purpose being that no matter what safeguards you put in place it will always be vulnerable to attack.

  • http://michael.theirwinfamily.net Michael

    Great post! It’s always good to remember the security. Thanks!

    • http://michael.theirwinfamily.net Michael

      Is it too late to show what the encrypted values look like in the tut? i.e., the value that the HMAC hash ends up looking like? I think that would be pretty neat to see as well. If not, no big deal.

  • http://www.dsaportfolio.com.br Diego SA

    That’s awesome! A simple thing that could bring a safer system than a lot out there. Awesome tutorial. Thanks a lot!

    • http://www.circuitbomb.com Dustin Blake
      Author

      Glad you like the tut! Your welcome.

  • http://webnv.net Nick

    Is it wise to store the salt in the database, right next to the salted password? Doesn’t that kind of defeat the purpose of salting a password?

    • Mark

      I would suggest two types of “salt” a unique one stored in the database and a common one stored in a PHP configuration file (not stored in the shared web root). The stored salt helps to prevent password brute forcing/dictionary attacks and the configuration salt will help to prevent access to your web application if the database/user table is compromised (say through sql injections), but not the file system.

      So when creating the password hash you would do something along the lines of this:

      $hash = hash_alg($CONFIG_SALT.$pwd.$salt_gen);

      Personally I do something like this:

      $hash = hast_alg(hash_alg($CONFIG_SALT.$pwd.$email).$salt_gen);

      Double hashing helps to make sure that the hash cannot be brute forced or guessed. It would take much much longer for a dictionary attacker to guess that hash 4er87f4d535fdf5331d389d7d32b1801f20d2e6 is a hash of d9b36e6b08845331d38937cd7d32b1801f20d2e6 rather than a hash of say “mysalt.dog.dog@gmail.com.2345″ when they are able to retrieve 2/4 of those values from the database. This is kind of overkill, but when it comes to security nothing is guaranteed so you must secure things in depth and in breathe.

  • http://www.circuitbomb.com Dustin
    Author

    The HMAC output looks like :

    d9b36e6b08845331d38937cd7d32b1801f20d2e6

  • http://blog.complimedia.com Montana Flynn

    As a PHP beginner I enjoyed your post very much.

    • Arvi

      Same here. Thanks Dustin. Great Tut!

      • http://www.circuitbomb.com Dustin
        Author

        Your welcome Arvi, I’m glad you found it useful.l

  • IgnacioRV

    You know? Tomorow I have a an information security exam at university…

    Thanks for the article, now I know how to implement some of the theory I’ve read about :)

    About SHA-1, the problem is that with today’s computing resources it’s not very resistant to collisions (it isn’t very difficult to get two pieces of text with the same result), but for small projects there should be no problems , of course it depends on what you will be encrypting… don’t use it for credit cards numbers or bank accounts passwords =P

    • http://www.circuitbomb.com Dustin Blake
      Author

      exactly, any system which handles highly sensitive information should always use the highest possible standard of encryption :)

  • http://aext.net Lam Nguyen

    Great post! I always look for security solutions in PHP. Thanks

  • http://www.sawmac.com/ Dave McFarland

    why are you using mysql extension (mysql_connect for example) instead of mysqli (mysqli_connect)?

    • Callum

      Does it really matter? It makes no difference to how the code executes.

      • http://www.circuitbomb.com Dustin Blake
        Author

        If the example were to be used in a live deployment to handle users, mysqli would be preferred. Using the regular mysql extension instead of mysqli is basically for backwards compatibility for older database’s. I certainly hope nobody is still using pre mysql 4.1, but I didn’t want to make that assumption in my example.

        I also used the insecure md5 hashing function in the salting example, but did not talk about it in the Cryptography section.

        At this point msql and mysqli are still a manner of preference, personally I use mysqli but still find myself using the older method from time to time.

  • Erik

    Well, The guys at MySQL clearly state that people should start using MySQLi – MySQL(improved).

    However, you’re correct – no real big importance. I think it’ll be considered a best practice thing in the future.

    Jeffery Way uses it. I use it >< —- Thats the motto I use these days.

  • http://www.kiararealty.com.my KA

    Thanks for the awesome tutorial again!

    • http://www.circuitbomb.com Dustin Blake
      Author

      Your welcome!

  • http://www.foxyturkey.com/ Yigit Ozdamar

    Great post! Safety first!!! lol

  • http://www.codeject.com Ryan

    Awesome tutorial – so detailed too. Thanks :)

  • http://www.jsxtech.com Jaspal Singh

    Great Tutorial, best of security lessons for php developers.
    Thanks for sharing.

    • http://www.circuitbomb.com Dustin Blake
      Author

      Your welcome, always glad to share :)

  • http://studyinfo.whatelseonline.com blues

    Great tutorial indeed. It’s gonna be very helpful in my next work.

  • Roger

    Some good stuff here. Thanks.

  • http://devesigner.com Lamin Barrow

    Nice post. Thanks for the code snippets.

  • http://www.solunanet.com Robert

    The password salting techniques are not ideal, at all. The biggest issue is with MD5 itself- this is a fairly common mistake, mostly because it keeps getting perpetuated. MD5 was designed with speed in mind, and in this case thats a bad thing. If you use a hash that takes twice as long to run its going to take hackers twice as long to generate rainbow tables against it.

    The ideal hash method would be to use bcrypt, which is supported natively in php 5.3 and through extensions in earlier versions. If thats not available you can use something like whirlpool and just loop it through a hundred times. Or, perhaps even better, you can use one of the many password libraries put together by experts.

    For reference, you’re in good company on this mistake. Jeff Atwood, of CodeHorror fame, wrote an article about passwords which prompted Thomas Ptacek to write this fantastic article about it-

    http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html

    • http://www.circuitbomb.com Dustin Blake
      Author

      As I wrote:
      //md5 hash the combined password * Note: md5 is only used in this scenario as an example

      And right. md5 is fail, that’s why I didn’t even make mention of it in when I discuss hashing. Ptacek is absolutely correct about slowing down the hashing function and why.

      A salt can be applied into a hash in a variety of ways, it’s not limited to being appended before or after the password.

      The argument for ‘whats best’ or ‘ideal’ can go on forever, and if you ask me it’s not whats important. Whats important is ‘whats good’ and its application within development.

  • http://www.w2point.com Web 2.0 Tools

    Useful tutorials, thanks…

  • Simon

    Thanks for the nice tutorial. I didn’t know about the hash() syntax.
    I’m always wondering, what about performance ? Is sha1 slower than md5 ? What about sha1 vs sha2 ? Is the mcrypt function stressful ? If someone knows some good articles about these points I would appreciate it !
    Thanks again :)

  • http://bensampson.net/ Ben

    Really good post, thanks!

    I’ll definitely be putting some of these examples into practice. And i finally know what salting is :D

    • http://www.circuitbomb.com Dustin Blake
      Author

      I’m glad you found the info useful.

  • http://juliusbeckmann.de/blog/ Julius Beckmann

    I wrote a class for secure password hashes. Take a look at it:
    http://juliusbeckmann.de/blog/easy-to-use-and-secure-php-hashing-class.html
    It uses random salts, iterations and permutations and you can create own hashing methods.

  • Hour

    it’s = it is

  • Chris

    This tutorial is awesome! Easy explanation and deployment of security mechanism in PHP every web developer should know about!

  • Fábio Antunes

    Hi.
    Awesome tut, really good.

    I was “ahhhhh” when i rote “print_r(hash_algos());” and have run it.

    You could post something about some of those more unfamiliar “hashing” algorithms, that we can in PHP and others.

    PS: You should also mentioned not to keep connection details (your “db_config.php”) inside the public_html / htdocs / www folder.

    Any way. Very Good.
    Thanks.

  • http://createmy.com.au Dale

    Just wondering if it you could generate salt using an algorithm?

    Say:
    1. Get all of the ASCII values of the password
    2. Sum up the values
    3. Times the sum values by the amount of letters
    4. Plus each of the digits in the returned results together and keep doing so till you get a number between 1 and 9
    5. Have 9 salt values and use the one corresponding salt
    6. Use MD5 or other for the password and salt

    Dale

  • Lisa

    I already had a basic understanding of most of these techniques but now I understand them even better. This is the best article I’ve read on the topic, clear and informative. Thanks!

  • Andrew

    I’m just taking a beginners php/mysql class now, and this was fan-fing-tastic. I seriously just finished the first 3 chapters in my book, then came across this… it was completely comprehensible. I think that says a lot about how well written of an article it was.

    It would be interesting to “zoom out” and talk about the theory behind all this… like how taking these steps will make your site/app more secure based off what the attacker is likely to do and what tools he/she has. I kind of assume that a lot of people here already know that side, but for a beginner it would be very useful to understand the logic.

    Anyway… enough rambling… seriously great article.

  • http://twitter.com/kevinquillen Kevin Quillen

    Code obfuscation by hand? Thats insanity.

  • joel

    a mislabeled article, as it was more a generic discussion of general php hashing techniques, and really NOTHING to do with “locking down a website”.

    As such, it falls into the common IT flaw of taking ONE issue, and tossing an inordinate amount of resources and time on it without looking at not only the big picture, but the real picture.

    The entire premise of the article (as posited in the context of ‘locking down a site’) is wrong, as it is primarily about ENFORCING THE SECURITY OF ALREADY STOLEN DATA. A *real* article about ‘locking down’ a site, would look at some of the common, obvious, and some out of the box ways that websites are compromised.

    For instance, most websites are hacked due to..
    1. Exploited opensource platforms i.e. WordPress, Joomla, SMF forum which all are very popular and to this day have exploitable weakness.

    2. Poorly vetted code. Many of these ‘tut’ sites are to blame, tossing around ‘login’ code, ‘admin code’ which are very general, very basic, but are snapped up by newbies and somehow become ‘best practices’. As secure as your ‘salting’ of the Passwords and all the hashing that you do, if your site takes user content (like this one) and does not sanitize the inputs properly, then the site could be compromised and silently too, with a javascript key logger recording your key strokes (how’s that ‘salt’ working for ya?)

    3. Social engineering and guessing poorly chosen passwords.

    4. Cross site scripting (where people can take actions without even using the password)

    5. Ajax hacking. This is really the ‘poor code’ mentioned earlier, but I say it here again, as you see it in sites that are otherwise quite robust, but have some ridiculously flawed ajax routines that are the weak link to penetrate and compromise the site.

    6. Phishing. where a cloned copy of your site’s admin panel is presented with the hope you try to login to it.

    there’s more of course -maybe if you were gonna write a REAL article you might do some research

    • http://www.circuitbomb.com Dustin
      Author

      Did you even read it?

      Nowhere in the article did I state “Hey these techniques are going to keep your website hacker-proof”, that would just be…dumb. Of course you provided excellent examples of attack methods, where are your examples of defending against such attacks?

      Your only argument is what the article lacked. Which I could see as a viable argument if I would have said ‘hey this is what your going to learn’, but I didn’t, in the introduction I specify what the article will be going over.

      If your so unhappy with what tutorial sites publish then why don’t you enlighten us with your own?

      • Pedro Henrique

        Don´t bother man, he just had a bad day.

        Easy is to criticize, hard is to make it done.

        Maybe we´ll see some good information from ‘joel’ in the next weeks. Maybe not.

      • Rick

        Your right Dustin!

        Joel; if you know so much, and better, then please improve the online community by publishing your own tutorials. For example; instead of only mentioning your point 6, tell me, how can I prevent myself from it? Ow, and this time write a REAL comment ;)

        The only thing I was thinking of, regarding the encryption of the scripts, is indeed ZendGuard (www.zend.com, mentioned above in comments) or Ioncube (www.ioncube.com). I have recently tested a php application for my work, in order to determen if it adds value to the business. This application was encoded with ZendGuard. As far as I have tried, there is just no f*cking way to do anything in that code. It was completely locked.

        This might be of great value when you want to sell an application on license base. You encrypt the licensing part and leave the rest open to give your costumer full control. Don’t ask me how it exactly can be done, but I’ve seen applications around which use this technique. (like http://www.kayako.com)

      • Kevin Jensen

        I want to see this tutorial on how to stop phishing. That will be a good one.

  • http://www.visual-blade.com Daquan Wright

    Even if the article has flaws, the concepts look to revolve around protecting your data and honestly anyone building a web app will have to research methods of data protection for their own respective projects (a tutorial can only do so much). Just than an article isn’t here to provide us with pretty code but instead remind us to never trust user input is a great thing.

    Good article Dustin. He won’t be writing any articles to show off his knowledge most likely, words are cheap.

  • http://myfacefriends.com Myfacefriends

    another useful and wonderful tuts… keep on shinning…. many thanks. awesome!

  • sharin_sg

    this is a useful and helpful tutorials. thanks for sharing.

  • Steve

    Seems that this isn’t really techniques to lock down your website but lock down your PHP passwords…… I thought this would be more of explanation of permissions and what can be done to help lock your site down from the title.

    There are more commercial products like zend encoder and ioncube loader that can help lock your code. In particular you want to protect sensative files such as db.php since anyone can view the source (generally) when on shared hosting.

    Also it’s good practice to protect your DB scripts in even of remote script execution exploit as well. No mention of XSS either… I should write an article :)

  • http://www.tabligheno.com/cat135-349-40__دستگاهتردمیل.html Stok

    Hi, tnx for this,but not enough

  • http://www.xaby.com Xaby

    a really good post! though i dun really understand some of the quotes

  • http://www.sinetics.ro Cosmin

    Hi. Great tut on locking the php source code. I’ll study this more, this is interesting…

  • http://bit.ly/4azPua RedPyxll

    Great tutorial, posted to my new tech blog at RedPyxll. http://bit.ly/4azPua
    Thanks.

  • Imran Khan

    Thanks nice post, ill have a deep look at it.

  • http://www.dev-hq.co.uk Joe

    Pretty good security tips!

  • http://www.bogdanpop.info Bogdan Pop

    Before securing your site, you’d better off securing your server. A super doooper secured site can be teared apart if the server running it has bad security configurations and blank root passwords.

  • http://www.dremi.info dr.emi

    hey! I want to know how to create encoded script like on “Obfuscation in PHP”

  • Karlos

    You show your MySql errors to the public??????? Surely this is one of the first lines of defense in securing your database and website scripting. Im shocked.

    mysql_connect($db_host, $db_usr, $db_pass) or die(“MySQL Error: ” . mysql_error());

    You also use md5 in one of your scripts. This is now broken and no longer presumed industry standard.

    And the below line is unecessary as you could just use the MySql respose to identify if theres a matched record.
    if(mysql_num_rows($checklogin) == 1)

    • http://www.circuitbomb.com Dustin
      Author

      Thanks for the response, I show my errors when I’m developing a website, or a script, up until I make it available to the public, unless you intend to copy and paste this for you own implementations, yea, your gonna show MySQL errors unless you fix it yourself.

      Yes I used MD5 as an example, I know MD5 is broken, I assume you had no intention to read commented code.

      • http://www.paulchater.co.uk Paul Chater

        I think that some people should really re-read and reiterate to themselves the title of this post, “SIMPLE” would be a key word. Haha.

        I think now-a-days practically every coder knows that MD5 is indeed broke, and should use one of the SHA methods with salting. It’s interesting… Although I definitely wouldn’t recommend storing the string in the database. Heh that’s just askin’ for trouble in my eyes.

        The way I encrypt is using an encryption key of a random string sha1-hashed, then hashing that hash again and using that hash as the salt and then hashing the actual users password with the salt appended. Personally I think it’s very secure haha, but I think I’d need a crypto-geek to tell me if it’s a highly secure way.

  • Kingdutch

    I’m too lazy to read all the comments so I dunno if no one else posted it yet.

    But am I the only one to notice in 3. Authenticating the user you actually only need a valid username? As your SQL never actually checks against the password? ^^

    (You first use the username to get salt and e-mail and then match again just against the username)

  • Brad

    For some reason there seem to be a lot of people here who didnt understand these were examples, not straight code to use on your site. To use this material you must understand it and then modify it for your use.

    Getting beyond that, thanks for the tut. I am now using hash(sha512) on my sites salted with the time stamp at the time they registered. Yes its stored in the database, but you have to get past the sha512 hash to get to it.

    Thanks again, well done.

    • http://www.ciruitbomb.com Dustin
      Author

      Very nice touch with the added timestamp.

  • http://ubuntu-for-humans.blogspot.com/ speedy18us

    I never saw such a complete tutorials on the web. I’ll read them all, ’cause I love them. Many thanks!

  • andrew

    I see you use the email in the hash for the password:

    What happens if the user wishes to change their email?

    • http://circuitbomb.com Dustin
      Author

      What usually happens? I suppose requiring a user to provide their password to make certain changes would be required, right? So you require a password to change an e-mail, or even the old password etc, so that you can use that same information to re-construct the process.

  • http://www.xboxgamertag.com/ Xbox

    Great tips thanks!

  • http://www.helpstar.com/ Lisa

    Good effort about this web security tutorial. But how is it securing this because a baby hacker can break this code easily. It just look for PHP passwords not for fully secured website. For this defiantly we need secure hosting and secure server.

  • http://healthenfermeradesalud.blogspot.com cutecankil

    nice and interesting keep it up!!