how secure are php codes/scripts when they are deployed in a server (or when they become online)? if i put constants and/or passwords in my php codes, will they be visible and be 'sitting duck' targets for hackers?

Recommended Answers

All 30 Replies

Your script can be as secure or insecure as you want.

Generally, the end user would not see constants or any of the actual code as this is executed on the server. All the end user should see is the output of any functions in your script.

If you are worried that a function may output some important data, use an @ symbol before it to suppress the standard errors: @mysql_connect("...", "...", "..."); Or better, add error handling into your code to make sure that if an error occurs then you have a specific response for it.

commented: Good points +6

thank you for the information, xan. it was a great help..

Also, make sure that you never send unencrypted passwords via GET as they will be visible in the URL. There are also hacking tools which allow the retrieval of POST data, so watch out for that too.

Also, make sure that you never send unencrypted passwords via GET as they will be visible in the URL. There are also hacking tools which allow the retrieval of POST data, so watch out for that too.

Even better yet, use javascript to encrypt the passwords before sending it over $_POST. This way if the post data is hacked the data is still encrypted. This sort of hack attack can happen when a hacker attaches a device to a fiberoptic cable to scan data running past. Also as a security question, is there any security difference between the following two codes because a tutorial years ago told me there was but find hard to believe.

mysql_connect('localhost','root','password111');

//or

$host='localhost';
$user='root';
$pass='password111';
mysql_connect($host,$user,$pass);

Those are the two scripts but the tutorial (I forget where) says the second script should be more secure although I don't see how. And it was also said in the tutorial that it would be even more secure to place the variables in an include() file. Is that true or just a myth?

Even better yet, use javascript to encrypt the passwords before sending it over $_POST. This way if the post data is hacked the data is still encrypted. This sort of hack attack can happen when a hacker attaches a device to a fiberoptic cable to scan data running past. Also as a security question, is there any security difference between the following two codes because a tutorial years ago told me there was but find hard to believe.

mysql_connect('localhost','root','password111');

//or

$host='localhost';
$user='root';
$pass='password111';
mysql_connect($host,$user,$pass);

Those are the two scripts but the tutorial (I forget where) says the second script should be more secure although I don't see how. And it was also said in the tutorial that it would be even more secure to place the variables in an include() file. Is that true or just a myth?

Very true. All sensitive data should be stored above the web root. Along with classes and other functions. Think if something happened to the server and it stopped parsing php and your code was presented in plain text. If everything is where the user can't get to it there is no way they can look through it.

Also,

Passwords should always be hashed, no matter what.

If you are sending info that you wouldn't want intercepted you should be on a secure connection (https) using a ssl certificate. The day rsa keys are able to be decoded is the day the world collapses.

The company I work for forces us to use ssl for user login, members areas and registrations. You should do the same, if you can afford it.

If you are wanting to store credit card info or ssn numbers, don't. If you must then you will need a virtual private server and heavy encryption. There are laws for this stuff.

commented: Excellent advice on all points given :) +6

[EDIT] Duplicate post somehow

Even better yet, use javascript to encrypt the passwords before sending it over $_POST. This way if the post data is hacked the data is still encrypted. This sort of hack attack can happen when a hacker attaches a device to a fiberoptic cable to scan data running past. Also as a security question, is there any security difference between the following two codes because a tutorial years ago told me there was but find hard to believe.

mysql_connect('localhost','root','password111');

//or

$host='localhost';
$user='root';
$pass='password111';
mysql_connect($host,$user,$pass);

Those are the two scripts but the tutorial (I forget where) says the second script should be more secure although I don't see how. And it was also said in the tutorial that it would be even more secure to place the variables in an include() file. Is that true or just a myth?

Using JavaScript to encrypt passwords is not something I'd recommend. Anything that is client side can be bypassed. An attacker sniffing the network can modify the HTTP request response to their benefit.

Very true. All sensitive data should be stored above the web root.

I think you meant below the web root?
It is very useful to practice this. Not just to remove the possibility of the HTTP server accidentally serving the file as text, but also to disable remote access of the PHP files in an order not intended.

Imagine having an index.php where you want all requests to be made. Then you have page2.php

On this page you have some variables that should have already been defined. If page2.php was accessed directly from the web, instead of through index.php then you have unintended behavior.

Using JavaScript to encrypt passwords is not something I'd recommend.

Well I think you mis-understood exactly what I meant. The process I was refering to was that javascript encodes the data first then php decodes it then php re-encodes the data.

I think you meant below the web root?

No because this way the user cannot access the file when apache is displaying the php code instead of html code. A rare problem but does happen. An example of including the files from above the web root:

include('/home/exampcom/phproot/file.php');

Where in that example the folder phproot is a directory with php files which is not in the web root to prevent any access at all.

Well I think you mis-understood exactly what I meant. The process I was refering to was that javascript encodes the data first then php decodes it then php re-encodes the data.

I would agree with digital-ether on this.

I always browse in Firefox with NoScript enabled (which means JavaScript is disabled for untrusted or unknown sites)

Lets say I visit your site with Javascript off, I enter a password which is not encoded before sending, meaning that your PHP script will get an unencoded password and will try to decode it.

Also, if you are encoding with JavaScript, an unfriendly user would be able to see exactly what you are doing and could reverse it anyway.


As a rule of thumb, I use JavaScript to make things 'pretty' after I have completed a project. I would never rely on JavaScript to handle even the smallest part of the security on any of my sites.

Well the only thing is that the value javascript encodes isn't the value that's stored in the database. Php would have to change that value to something like a hash. Also as for the problem of javascript being disabled - perhaps Java or Flash would be a better language.

Well I think you mis-understood exactly what I meant. The process I was refering to was that javascript encodes the data first then php decodes it then php re-encodes the data.

I actually do understand what you're saying.

Let me give you an example of why you should not rely on the client hashing passwords for you, unless you can verify the integrity of the data transmitted.

Sever has a page, login.php
It has a Login form, and field, "password".
Server also sends some JavaScript that hashes password.

Server sends this to a client via a HTTP response:

An attacker has managed to take over the TCP session between the client, and server. Thus all HTTP requests are being proxied through their machine.

Attacker's machine has a script, that removes the javascript that hashes the password.

Client machine receives form, with no hashing. User does not realize that when they submit the form, they have sent a plain text password.

Attacker receives the plain-text password. Attacker encrypts the password with the algorithm expected by the server. Attacker forwards the HTTP request to the server.

The server does not realize that they have made the users password available to a remote attacker.

The reason TLS is able to keep the data safe, is that it ensures the integrity of the data. So an attacker cannot modify a HTTP request, nor should they be able to read it.

No because this way the user cannot access the file when apache is displaying the php code instead of html code. A rare problem but does happen. An example of including the files from above the web root:

include('/home/exampcom/phproot/file.php');

Where in that example the folder phproot is a directory with php files which is not in the web root to prevent any access at all.

I was merely commenting on the use of "above", in "above the web root". We are referring to the same thing here, it is just that I view the directory structure as a tree, while you're viewing it as an inverted tree. Thus when you say above the web root, I say below the web root.

I think generally programming refer to hierarchical structures as inverted trees, so I think the better term is "above the web root".

I actually do understand what you're saying.

Let me give you an example of why you should not rely on the client hashing passwords for you, unless you can verify the integrity of the data transmitted.

Sever has a page, login.php
It has a Login form, and field, "password".
Server also sends some JavaScript that hashes password.

Server sends this to a client via a HTTP response:

An attacker has managed to take over the TCP session between the client, and server. Thus all HTTP requests are being proxied through their machine.

Attacker's machine has a script, that removes the javascript that hashes the password.

Client machine receives form, with no hashing. User does not realize that when they submit the form, they have sent a plain text password.

Attacker receives the plain-text password. Attacker encrypts the password with the algorithm expected by the server. Attacker forwards the HTTP request to the server.

The server does not realize that they have made the users password available to a remote attacker.

The reason TLS is able to keep the data safe, is that it ensures the integrity of the data. So an attacker cannot modify a HTTP request, nor should they be able to read it.

It is only this part of the situation that makes that possible.

Attacker forwards the HTTP request to the server.

If however the attacker enters the password into the webpage, then when javascript and php both encode the password, because javascript has encoded it twice, the password will not match. Keep in mind php still encodes the password with this system. It is an additional layer of security.
Edit: But it is probably best if Java or Flash is used.

It is only this part of the situation that makes that possible.
If however the attacker enters the password into the webpage, then when javascript and php both encode the password, because javascript has encoded it twice, the password will not match. Keep in mind php still encodes the password with this system. It is an additional layer of security.
Edit: But it is probably best if Java or Flash is used.

Having Java or Flash do it still doesn't make any difference. It is still client side.

The problem here isn't the encyption/hashing. It doesn't matter how many times you hash the password. In fact, hashing a password twice makes it less secure.

The problem here is data integrity. If you cannot ensure the browser that the data you sent it has not been modified.

TLS ensures this: http://www.javvin.com/protocolTLS.html

Hashing on the server side, only protects you against viewing of the data in storage. Like someone viewing passwords your database. It does not protect you against the sending of the password from the client, so you can leave it out in that context.

The hashing of the password on the client side, does protect it from viewing while sending to from client to the server.

However, without ensuring the integrity of the data being received by the client, then the hasing of the password will not occur in the first place. So the password will be sent as plain text.

In fact a lot of sites will hash passwords on the client with JS. For example Yahoo! login (MD5), and Meebo IM (SHA-256 and RSA).

sources:
Yahoo: https://s.yimg.com/lq/i/reg/js/login_md5_1.1.js
Meebo: http://js.meebo.com/script/meebo_v78.js?1252058884

However, both use TLS to transport the login data. Yahoo! has the whole login page under HTTPS.
Meebo however, only has the login form, under HTTPS.
http://www.meebo.com/security/

I would not recommend what meebo does. In fact their not putting the login page under TLS makes their use of TLS useless, but that is a different discussion.

The hashing of the password on the client side

The thing is, its not hashing on client side. It's hashing on server side but using a reverible encoder on client side. I'll write an example so we can get over this loop hole.

Here is the example of secure password transfer and storage:

<head><title>Secure Post Transfer</title><script>
function sendpost() {
    var data=document.getElementById("data").value;
    data=data.replace(/--|-\+\+\+2\+/,"---|-+++2+").replace(/--|-\+\+\+8\+/,"---|-+++8+").replace(/\+\+|-\+--8-/,"++|-+--8-");
    data=data.replace(/([0-9]+)/g,"--|-+++2+$1--|-+++8+").replace(/([0-9])/g,"--|-+++8+$1--|-+++2+");
    data=data.replace(/([a-z])/g,"++|-+--8-$1++|-+--8-");
    document.getElementById("data").value=data;
    document.dform.submit();
    return true;
    }
</script></head><body>
<form name="dform" method="POST">
<textarea name="data" id="data" style="width:400px; height:150px;">Add some random text in here aza</textarea>
<input onclick="javascript:sendpost();" value="Search" type="button">
</form><?
function truehash($hash) {
    return hash('crc32b',substr(hash('whirlpool',$hashzzz),64));
    }
$var=stripslashes($_POST['data']);
$var=str_replace(array('--|-+++8+','--|-+++2+','--|-+++--|-+++8+2+','--|-+++2+','--|-+++8+','++|-+--8-'),'',$var);
$var=truehash($var);
echo 'Value to send to mysql: '.$var;
?></body>

I hope that explains it better because both php AND javascript are encoding the password so there is less chance of man-in-the-middle-attack.

Here is the example of secure password transfer and storage:

<head><title>Secure Post Transfer</title><script>
function sendpost() {
    var data=document.getElementById("data").value;
    data=data.replace(/--|-\+\+\+2\+/,"---|-+++2+").replace(/--|-\+\+\+8\+/,"---|-+++8+").replace(/\+\+|-\+--8-/,"++|-+--8-");
    data=data.replace(/([0-9]+)/g,"--|-+++2+$1--|-+++8+").replace(/([0-9])/g,"--|-+++8+$1--|-+++2+");
    data=data.replace(/([a-z])/g,"++|-+--8-$1++|-+--8-");
    document.getElementById("data").value=data;
    document.dform.submit();
    return true;
    }
</script></head><body>
<form name="dform" method="POST">
<textarea name="data" id="data" style="width:400px; height:150px;">Add some random text in here aza</textarea>
<input onclick="javascript:sendpost();" value="Search" type="button">
</form><?
function truehash($hash) {
    return hash('crc32b',substr(hash('whirlpool',$hashzzz),64));
    }
$var=stripslashes($_POST['data']);
$var=str_replace(array('--|-+++8+','--|-+++2+','--|-+++--|-+++8+2+','--|-+++2+','--|-+++8+','++|-+--8-'),'',$var);
$var=truehash($var);
echo 'Value to send to mysql: '.$var;
?></body>

I hope that explains it better because both php AND javascript are encoding the password so there is less chance of man-in-the-middle-attack.

If you can easily derive the password:

str_replace(array('--|-+++8+','--|-+++2+','--|-+++--|-+++8+2+','--|-+++2+','--|-+++8+','++|-+--8-'),'',$var)

Then it is as good as being sent plain-text.

I understand that this could be useful to mitigate against automated password sniffing programs that extract passwords off the network blindly. It doesn't protect against a man-in-the-middle attack however for the reasons I already posted.

If you can easily derive the password:

str_replace(array('--|-+++8+','--|-+++2+','--|-+++--|-+++8+2+','--|-+++2+','--|-+++8+','++|-+--8-'),'',$var)

Then it is as good as being sent plain-text.

I understand that this could be useful to mitigate against automated password sniffing programs that extract passwords off the network blindly. It doesn't protect against a man-in-the-middle attack however for the reasons I already posted.

That I would agree with because although this type of script does not much extra in security, it still does something.

No because this way the user cannot access the file when apache is displaying the php code instead of html code. A rare problem but does happen. An example of including the files from above the web root:

include('/home/exampcom/phproot/file.php');

Where in that example the folder phproot is a directory with php files which is not in the web root to prevent any access at all.

how do you include files above the web root again? do you mean that files containing constants should be saved above the folder containing the index.php file (or index.html)? or like

inlcude('folder_containing_the_index.php/folder_containing_the_files_with_constants/constants.txt')

thanks..

Yes that is exactly what they are saying, although it would not be a txt file but a php file. Many sites also add a .inc extension to include files, for example:

include("home/includes/constants.php.inc");

Yes that is exactly what they are saying, although it would not be a txt file but a php file. Many sites also add a .inc extension to include files, for example:

include("home/includes/constants.php.inc");

Except you need to begin with a slash. Below is a corrected example of the above quote.

include("/home/includes/constants.php.inc");

Except you need to begin with a slash. Below is a corrected example of the above quote.

include("/home/includes/constants.php.inc");

That is incorrect. Your example is an absolute path, mine is a relative path, both of which are perfectly legal. However mine does rely on the path from where the script is being run whereas yours does not, so is probably a safer option.

That is incorrect. Your example is an absolute path, mine is a relative path, both of which are perfectly legal. However mine does rely on the path from where the script is being run whereas yours does not, so is probably a safer option.

Well if you are going to use a relative path and the page is in the same folder as htdocs or public_html then you will need to use the following instead as again your relative path leads inside the web directory.

include("../includes/constants.php.inc");

I'm ab bit confused on what you guys are saying:

Say I have this as the web root:

/home/public_html/

Should I save my php constants in:

/home/public_html/includes/

or

/home/includes/

I'm ab bit confused on what you guys are saying:

Say I have this as the web root:

/home/public_html/

Should I save my php constants in:

/home/public_html/includes/

or

/home/includes/

Your passwords (eg. php-mysql scripting passwords) should be located at /home/includes/ where it cannot be accessed through the http protocol. In otherwords not for public viewing. By doing this the server can still include the script but nobody can type in the url to the script because there is no url to the script due to the fact that it would not be in the web directory.

The browser won't accept that sort of url because the browser will treat the /../ as a folder called .. . In otherwords you can't make the browser go up a directory using that method nor can you with any other software.

The browser won't accept that sort of url because the browser will treat the /../ as a folder called ..

I'm sorry, but that's just plain false. It is possible to access other folders on a server (even below/above the root directory if they aren't protected properly). I've done it before, and I've just double-checked that it can be done on our servers. You need to filter request headers for '..' and '.' for this specific reason.

The browser won't accept that sort of url because the browser will treat the /../ as a folder called .. . In otherwords you can't make the browser go up a directory using that method nor can you with any other software.

The path in a URL, is an internal representation of a resource. The resolution of that path to the actual resource (can be a file system, or other stored data) is left up to the server software. However, to normalize URLs (make URLs pointing to the same reference equivalent) there are guidelines defined in:

http://www.ietf.org/rfc/rfc3986.txt

For the use of ../ see the section: "Remove Dot Segments"

Firefox follows this rules as far as my test. And since this resolution does not specify client or server, then doing it on the client is the same as the server.

eg: If you put:

http://example.com/test/.../

Into Firefox 3.5 it will resolve to:

http://example.com/test/

If you create a raw HTTP request:

GET /test/../ HTTP/1.0
HOST: example.com

The server on example.com resolves the path /test/../ to /test/ However, if you send Apache a request like:

GET /../ HTTP/1.0
HOST: example.com

It returns a malformed request error.

In the context of serving files. The serving of files in a directory is not based on the path in the URL. It is restricted by the web server's configuration. In apache, the normal setup is to restrict access to all files on the system:

eg:

<Directory />
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
</Directory>

This restricts access to every single file, since "/" is the base directory.

Preceding this you usually have the portion that allows access solely to the web root.

<Directory "/var/www/html">
    Order allow,deny
    Allow from all
</Directory>

Here the web root is /var/www/html and allowed to be accessed by everyone from HTTP (the web).

With this configuration it does not matter how the URL is formed, it if resolves to a file not in /var/www/html it will not be served.

So following whats been discussed, it is best to put your sensitive PHP files where they cannot be accessed from the web. In this example:

/var/www/includes/

On some hosts however, you may not have access to directories below the web root. If you can edit your Apache configuration file, ie: HTTP.conf . Then add an entry disabling access to the folder you store sensitive data in:

<Directory "/var/www/html/includes/">
    Order allow,deny
    Deny from all
</Directory>

So now you can safely put files in /var/www/html/includes/ which is still in your web root.

If you can't edit your HTTP.conf file, they could could add it via a .htaccess file.

The simplest is just put a .htacess file in the directory you want access to restricted. With the contents:

Order allow,deny
Deny from all

That will make sure that directory is not served by Apache.

I'm sorry, but that's just plain false. It is possible to access other folders on a server (even below/above the root directory if they aren't protected properly). I've done it before, and I've just double-checked that it can be done on our servers. You need to filter request headers for '..' and '.' for this specific reason.

Are you talking about access from PHP, or from the server? What server are you using?

The server will never serve anything that it has not been configured to serve. Usually, this means anything below the web root. If your server is serving files below the web root, then you have a misconfiguration.

However, PHP is not restricted by the severs configuration. The server's configuration is only for the resolution of the path section of the URL to files, not the restriction of access to the filesystem.

PHP is only restricted to files the PHP process can access. This depends on the owner of the PHP process. Usually, PHP is just spawned off the Apache parent process, eg: httpd, so the user is httpd, thus it can access any files accessible by the user httpd. (This is mainly true for Linux, on windows before Vista, you can access just about anything)

However, you can restrict the access with open_basedir, but this has been deprecated and is removed in PHP6.

You can also use suPHP, which runs PHP under the user that owns the PHP script. So if you uploaded a PHP script via FTP under the user "joe" then PHP would run as "joe".

http://www.suphp.org/Home.html

This makes it so PHP is restricted to the directories your user account is restricted to.

I'm sure there are other methods. However, these methods are solely to help secure PHP, not offer full security. You will have to write your code so that your PHP does not include arbitrary files.

a good post on the topic: http://blog.php-security.org/archives/72-Open_basedir-confusion.html

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.