Web Development using PHP and MYSQL and AJAX and JAVASCRIPT,php source code,php5,php web links,php tutorial
Saturday, August 1, 2009
PHP Session Management
There are several parameters that can be manipulated to change the behavior of the PHP session management. These parameters are set in the php.ini file in the section headed [Session].
session.save_handler
This parameter specifies the method used by PHP to store and retrieve session variables. The default value is files, to indicate the use of session files, as described in the previous sections. The other values that this parameter can have are: mm to store and retrieve variables from shared memory, and user to store and retrieve variables with user-defined handlers. In Appendix D we describe how to create user-defined handlers to store session variables in a MySQL database.
session.save_path
This parameter specifies the directory in which session files are saved when the session.save_handler is set to files. The default value is /tmp. When implementing user-defined save_handler methods, the value of this parameter is passed as an argument to the function that opens a session.
session.use_cookies
This parameter determines if PHP sets a cookie to hold the session ID. Setting this parameter to 0 stops PHP from setting cookies and may be considered for the reasons discussed in the previous section. The default value is 1, meaning that a cookie stores the session ID.
session.name
This parameter controls the name of the cookie, GET attribute, or POST attribute that is used to hold the session ID. The default is PHPSESSID, and there is no reason to change this setting unless there is a name collision with another variable.
session.auto_start
With the default value of 0 for this setting, PHP initializes a session only when a session call such as session_start( ) or session_register( ) is made. If this parameter is set to 1, sessions are automatically initialized if a session ID is found in the request. Allowing sessions to autostart adds unnecessary overhead if session values aren't required for all scripts.
session.cookie_lifetime
This parameter holds the life of a session cookie in seconds and is used by PHP when setting the expiry date and time of a cookie. The default value of 0 sets up a session cookie that lasts only while the browser program is running. Setting this value to a number of seconds other than 0 sets up the cookie with an expiry date and time. The expiry date and time of the cookie is set as an absolute date and time, calculated by adding the cookie_lifetime value to the current date and time on the server machine.[2]
[2] The actual expiry of the cookie is performed by the browser, which compares the expiry date and time of the cookie with the client machine's date and time. If the date and time are incorrectly set on the client, a cookie might expire immediately or persist longer than expected.
session.cookie_path
This parameter sets the valid path for a cookie. The default value is /, which means that browsers include the session cookie in requests for resources in all paths for the cookie's domain. Setting this value to the path of the session-based scripts can reduce the number of requests that need to include the cookie. For example, setting the parameter to /winestore instructs the browser to include the session cookie only with requests that start with http://www.webdatabasebook.com/winestore/.
session.cookie_domain
This parameter can override the domain for which the cookie is valid. The default is a blank string, meaning that the cookie is set with the domain of the machine running the web server, and the browser includes the cookie only in requests sent to that domain.
session.cookie_secure
This parameter sets the secure flag of a cookie, which prevents a browser from sending the session cookie over nonencrypted connections. When this setting is 1, the browser sends the session cookie over a network connection that is protected using the Secure Sockets Layer, SSL. We discuss SSL in the next chapter and provide installation instructions in Appendix A. The default value of 0 allows a browser to send the session cookie over encrypted and nonencrypted services.
session.serialize_handler
This parameter sets up the method by which variables are serialized, that is, how they are converted into a stream of bytes suitable for the chosen session store. The default value is php, which indicates use of the standard PHP serialization functions. An alternative is wddx, which uses the WDDX libraries that encode variables as XML.
session.gc_probability
This parameter determines the probability that the garbage collection process will be performed when a session is initialized. The default value of 1 sets a 1% chance of garbage collection. See the discussion in the previous section for a full explanation of garbage collection.
session.gc_maxlifetime
This parameter sets the life of a session in number of seconds. The default value is 1440, or 24 minutes. Garbage collection destroys a session that has been inactive for this period. See the discussion in the previous section for a full explanation of garbage collection.
session.referer_check
This parameter can restrict the creation of sessions to requests that have the HTTP Referer: header field set. This is a useful feature if access to an application is allowed only by following a hypertext link from a particular page such as a welcome page. If the HTTP Referer header field doesn't match the value of this parameter, PHP creates a session, but the session is marked as invalid and unusable. The default value of a blank string applies no restriction.
session.entropy_file
PHP generates the session IDs from a random number seeded by the system date and time. Because the algorithm is known-it can be looked up in the PHP source code-it makes guessing session IDs a little easier. If this parameter is set to the name of a file, the first n bytes from that file (where n is specified by the session.entropy_length parameter) make the ID less predictable. The default value is left blank, meaning the default seeding method is used. One alternative is to use /dev/urandom, a special Unix device that produces a pseudorandom number.
session.entropy_length
This parameter is the number of bytes to use when generating a session ID from the file specified by session.entropy_file. The default value is 0, the required value when no entropy file is set.
session.cache_limiter
This parameter controls how responses can be cached by the browser. The default is nocache, meaning that PHP sets up the HTTP response to avoid browser caching. PHP sets the HTTP/1.1-defined header field Cache-Control to no-cache, the HTTP/1.0 header field Pragma to no-cache, and-for good measure-the Expires header field to Thu, 19 Nov 1981 08:52:00 GMT. Applications that use sessions-and even stateless web database applications-can be adversely affected when browsers cache pages. The other values allowed, private and public, allow responses to be cached. The distinction between private and public is apparent when a proxy server caches responses. See Appendix B for more details about HTTP caching.
session.cache_expire
This parameter is used when caching is allowed; it sets the expiry date and time of the response to be the current system time plus the parameter value in minutes. The default value is 180.
• In Web applications, it is frequently desirable to:
– Remember if a user has visited a site previously
– Remember the sequence of pages visited during a session
– Associate information with a user session
• Like a shopping basket
• To accomplish these things, need to have “stateful” connections between client and server
– That is, association information (state) with the connection
– HTTP was originally designed to not be stateful,leading to the addition of the Cookie mechanism
Cookies
• A mechanism for adding state to HTTP requests.
• Permits name, value pairs to be preserved across multiple HTTP requests.
• Basic approach:
– Server sends a Set-Cookie HTTP header in its response.
– Value of the header includes name, value pairs.
– The client stores the name, value pairs, and proactively sends them to the server (in the Cookie header) with every request thereafter.
– The Cookie protocol piggybacks on top of HTTP
• Information flow is in the reverse direction of most HTTP requests
client server
GET
200 OK // Set-Cookie: name=“value”; name=“value”
GET Cookie: name=“value”; name=“value”
Cookies in PHP
• How Cookies are set in PHP:
– Use built-in setcookie() function. Most simple form is:
– setcookie(name, value)
• It is also possible to specify when the cookie will expire, the URL path and domain for which it applies (defaults to those of request URI).
• Accessing Cookie values:
– $local_variable = $_COOKIE[name]
• To delete a cookie, use setcookie with the same cookie name, and an expiration value in the past.
Problems with Cookies
• Problems with Cookies
– Browsers can refuse to accept cookies.
– Additionally, it adds network overhead to send lots of information back and forth.
– There are also limits to the amount of information that can be sent
– Some information you just don’t want to save on the client’s computer.
PHP Sessions
• The solution: store session information on the server,and have the client only store an identifier for its information as stored on the server.
• The identifier is known as a session ID. The session ID is stored using a cookie (can be passed as a GET parameter as well)
• The server then uses the session ID to retrieve the information it has stored on the server.
• Session information is typically stored in files on theserver, though options
exist for using shared memory,and also writing your own handlers (e.g., to use a
database for storage)
Using Sessions in PHP
• To start a session:
– session_start()
– Creates a session identifier
– Session identifier is passed between client and server either as a Cookie, or in GET parameters
• Then, can create, access, and modify session variables:
– $_SESSION[session_var_name] = value;
– $_SESSION is only available once you call session_start()
– $local_variable = $_SESSION[session_var_name];
– Can check if session variable is set by using isset();
• To end a session:
– session_destroy();
Security of Session Data
• In general, cannot guarantee that session data will remain private
• Often, the session data files can be read by any web application on the same server
• The session ID can be grabbed by looking at the GET parameters (for GET-based passing of the session ID),or by eavesdropping the on-the-wire protocol (to get the
cookie with the session ID)
– If the session holds a password, someone can then “replay” the session ID back to the server
• Cookie data, though stored on the client side, are sent across the wire n-the-clear
– Client machines might be compromised, such as by malicious
software inadvertently downloaded, or by a virus
Cross-Site Scripting (XSS)
Cross-Site Scripting, abbreviated XSS, is another common security issue. This
issue is relevant whenever content that comes from the user will be redisplayed
on the screen. It is essentially when Javascript is injected into the HTML source.
We could for instance imaging a forum. On a forum users will be able to post
messages that will be displayed for other users. We want the users to be able
to format their messages and HTML is just perfect for that, right? There is
just a minor problem. . . Not all users are equally nice. The same kind of people that might want to drop the school's student table from the previous section
might also want to do something here. Speci_cally what they might want to
do is insert Javascript into the source. This might be for various purposes. It
could be simply for annoying by creating an in_nite loop of alert messages which
would force the user to shutdown the browser or it could be redirecting the users
to websites such as goatse or tubgirl (you might not want to check what it is
if you do not already know). Other, more so_sticated attacks, could be writing
a keylogger that logs and sends keystrokes (such as passwords) to an external
website or the injected Javascript could be retrieving the users' cookies (more
on the latter later in this tutorial).
XSS protection As a matter of fact, this is rather easy to protect yourself from as well.
PHP has a nifty function that is useful in this instance which is called htmlentities().
It will simply convert characters which have a meaning in HTML to their cor-
responding entities. For instance, HTML tags start with a lower-than sign and
that particular character will be converted to <. If you care about validation of your HTML (and you should!) then this will also help along with that.
We just have one problem. Our original example was a forum system and we wanted to give the users the opportunity to format their posts. However,the _x we just implemented removed this opportunity so we need to give them an alternate one. One with which we can control what they may do and not do.
A common feature is called bbcodes. It has a syntax very similar to HTML and
I am quite sure you are familiar with it if you have ever frequented any forum.
Be aware though! You might get some additional XSS security holes with some
tags.
A common bbcode tag is the URL tag. We could imagine that someone en-
tered [url=http://www.phpfreaks.com]The best PHP website[/url] which
would be converted to: <a href="http://www.phpfreaks.com">The best PHP
website</a>. At _rst glance there is no issue with allowing that. However,
URLs like javascript:alert('Hi') are also allowed and they will, obviously,
execute the entered Javascript. Similarly, in some lower versions of Internet Ex- plorer (IE6 and below) that URL format is allowed and will execute Javascript
so we have to take care of that as well.
For both the two before mentioned instances we might want to check that
the protocol is one we would allow. It would be better to create a white-list of
allowed protocols instead of creating a black-list of disallowed protocols. Simply select the protocols you want (e.g. http, https and ftp) and disallow all other.
Finally, this XSS cheatsheet might be useful to you. Both when learning
about XSS as well as testing that your application is secure.
Outside File Access
Normally, pages ending with .php will be handled forwarded to PHP by Apache and therefore the code will be hidden from the users. That the source code is hidden is one of the things that characterizes server-side scripting languages such as PHP. However, the PHP module or Apache might fail and the code might be displayed in plain unparsed text to the user. This is definitely not good. First of all, if the source is visible then it is much easier to find security issues in your application. Additionally, some scripts contain configuration files within the document root (the directory in which all files and sub-folders are publicly acessible from the outside world) and those will obviously not be parsed either thus presented to the user if they enter the filename into the URL. Personally I have experienced this before where I was on a small website and suddenly a misconfiguration of some sort displayed the source code to me. The website used a widely used application and I happened to know where the configuration file was. Sure enough, I was able to view that as well and from that I gathered the root password for the server (bad security practice to use the same password for multiple purposes and it is also bad security practice to use the root MySQL user). Being a nice person I did not do anything with it, but other people might not be as nice as I am and if you have the root password for a server then you can essentially do anything with it.
Another instance of this is the popular website Facebook which you have probably heard about in some way or another. What I explained before (server misconfiguration resulting in leaked source code) also has also happened to Face-book. Even big companies with people paid to configure the server apparently sometimes screws up and therefore it is necessary to take some security pre-cautions in order to prevent source leakage if something like that should everhappen (something Facebook apparently did not).
It all has to do with how you layout your directory structure. So, all files within the document root can be retrieved by the user. Therefore we might as well move everything else out of there so people cannot directly access it. This means we might have index.php and some static files such as CSS, Javascript and images laying inside the document root. We can even take it further and do so the only thing that is in index.php is the following:
<?php
require '../public_index.php';
?>
That particular snippet is the only thing the user will ever be able to see
should something happen. So we might have a directory structure that looks
like this:
/application
/controllers
/models
/views
/library
/public_html<-- document root
/index.php
/media
/images
/javascript
/css
/config
/cache
/tmp
/public_index.php
/logs
By laying out your files in this manner you will prevent that people will see
things they are not supposed to see. It is easy to do so there is no reason why
you would not.
Remote File Inclusion
Remote file inclusion attacks (sometimes abbreviated RFI) is a vulnerability
many people probably do not know of, but it is a very serious issue that also
must be addressed. As the name implies, it is when remote files are included,
but what exactly does that? Let us look at an example:
<?php
$page = isset($_GET['page']) ? $_GET['page'] : 'home';
require $page . '.php';
?>This is a very basic front controller that will forward the request to whatever
file that should be responsible for that particular request.
Imagine that at http://example.com/malice.php a file exists and our script
is located at http://site.com/index.php. The attacker will do this request:
http://site.com/index.php?page=http://example.com/malice. This file will get
executed when it is included and it will a write a new file to the disk. This le
could be a shell which would allow people to execute commands to the terminal
from it as well as other things they should not bea ble to. Another thing the
attacker can do is set page to http://example.com/malice.php? (note the end-
ing question mark). That will make whatever follows it part of the query string
and therefore ignored by the server the file is getting included from. Why this is
a security issue should be pretty obvious. People should denitely not be able
to execute whatever commands they want on our server, so how can we prevent
them?
There are a couple of php.ini directives you can use to prevent this:
allow url fopen this directive is set to on by default and it controls whether
remote les should be includable.
allow url include this directive is set to off by default and was introduced in
PHP 5.2. It controls whether the include(), require(), include once()
and require once() should be able to include remote files. In versions
below PHP 5.2 this was also controlled by allow url fopen. Furthermore,
if allow url fopen is set to offthen this directive will be ignored and set
to offas well.
Basically those two directives will enable you to set the required security
settings you will need. Again, no data that is not from the inside of your
system should be trusted. You must validate user input and ensure that people
will not enter malformed or unexpected data.
One of our other administrators, Thomas Johnson, has written a small tu-
torial about how you can use Apache to block RFI attacks called Preventing
remote file include attacks with mod rewrite. You might want to check that out
as well if you are concerned about RFI vulnerabilities.
Session Security
Stealing the session ID
Imagine that you have a key for a vault in your bank. If you have the key
then you can get whatever is in the vault. The session ID works a bit like that.
However, your key for your vault can be stolen and similarly can the session ID
of your users (including you) be stolen or intercepted.
For the record, just because I used a vault/key analogy then it does not mean
that you should put secret or important data of some sort in your sessions.
Earlier we talked about XSS and I mentioned briefly that it could
be used to steal people's cookies. That is the most common way cookies are
stolen. This cookie could be PHPSESSID (or whatever you may have renamed
it to. When you steal a session ID and try to use it again it is called session
fixation. So. . . if you can get a valid session ID and that session is used for
something like authentication then you will essentially be logged in as that
user. Obviously that is not a good thing|especially not if the user is high
ranking with administrative privileges.
Issues with shared hosting
when there are multiple people having their websites hosted on a single server.
On a server with a Linux operating system session data will by default be stored
in the /tmp directory. It is a directory that stores temporary data and it will
obviously have to be readable and writable by everyone. Therefore, if your
session data is stored in there, which it is by default, then the other users can
find it if they look hard enough. This poses the same security issues as with
cookies being stolen using XSS.
Preventing session fixation
Now that we have talked a bit about how the session ID can be stolen then let
us talk a bit about how we can minimize the risk session _xation.
One thing we can do is to change the session ID often. If we do that then the
chance that the intercepted session ID will be valid will be greatly minimized
if that ID changes often. We can use one of PHP' built-in functions called
session regenerate id(). When we call this function the session ID will be,
no surprise, regenerated. The client will simply be informed that the ID has
changed via an HTTP response header called Set-Cookie.
If you are using PHP 5.2+ then you can tell the browser that Javascript
should not be given access to the cookie using a ag called httponly. You can
set this ag using the php.ini directive called session.cookie httponly or
you can use the session set cookie params() function.
Regarding the issue with the shared hosts, the _x is simple: store the data
where only you have access. You can use the directive called session.save path
to set another path for storing them. You can also store them in a database,
but then you will have to write your own handler using the function called
session set save handler().
Cross-site request forgery
Cross-site request forgery (CSRF) is when you trick the user into making a
request they have never made. Imagine that in your application it is possible to
delete users like this: /user/delete/Joe. That would delete the user with the
username \Joe". A malicious user might place this bit of HTML on his website:
<img src="http://example.com/user/delete/Joe" height="1"
width="1" />
This will basically trick the user into making a request to that page without
them knowing it. Obviously only people who are logged in as administrators
should be able to call this URL and therefore it will fail for most users. However,
if a logged in administrator goes to the page where the above piece of HTML is
located then the request will be successfully completed and \Joe" will be gone.
How can we prevent this? Well, in this case we could simply ask the admin
to verify the action with his password before performing it. Yes, I know, this is
kind of like Windows Vista's UAC (User Account Control) that people claim is
incredibly annoying and prompts them to verify their action every _fth millisec-
ond, but sometimes you will, unfortunately, have to add just a little amount of
nuisance in order to keep your application safe.
Had the account come from a form then we could simply require that the
information (in the previous case the username) be submitted using post and
read it like $ POST['username']. However, this adds only a minimum of extra
security. More sophisticated attacks than the above could just as easily trick
the user into performing a POST request instead GET. We could use the \enter
your password" method like before, but we could also use another kind of token.
Imagine this form:
<?php
session_start();
$_SESSION['token'] = uniqid(md5(microtime()), true);
?>
<form action="/delete-user.php" method="post">
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" />
Username: <input type="text" name="username" />
<button type="submit">Delete user</button>
</form>
Here we have added a hidden _eld called token and stored its content in a
session. On the next page we can do something like this:
<?php
session_start();
if ($_POST['token'] !== $_SESSION['token']) {
die('Invalid token');
}
// form processing here
?>
We simply check that it is a valid token and we have then successfully ensured
that the request did in fact come from the form
Directory traversal
<?php
$page = isset($_GET['page']) ? $_GET['page'] : 'home';
require $page . '.php';
?>
We will just say that this particular file is stored in the following path:
/home/someone/public html/index.php. The attacker could then do: in-
dex.php?page=../secret
That would give us /home/someone/public html/secret.php which would
otherwise have been accessible. I am sure you could think of more dangerous
situations than this particular one.
There are a couple of ways you could prevent this with. First of all you
could have an array of valid pages, e.g.:
$pages = array(
'home',
'login',
'logout',
// etc.
);
if (!in_array($page, $pages) {
die('Invalid page');
}
Another thing you could do is check that the requested file matches a par-
ticular format:
$file = str_replace('\\', '/', realpath($page . '.php'));
if (!preg_match('%^/home/someone/public_html/[a-z]+\.php$%',
$file)) {
die('Invalid page');
}
include $file;
Basically you need to verify that the entered information is valid and con-
forms to what you expected.
How to redirect browser to https (ssl) in php
Most of the e-commerce website uses payment gateway for online payment. And, those sites uses SSL (secure socket layer) connection to transfer data to and from the payment gateway.
In the common scenario, most of the sites uses “http” protocol and you can see “http” in the browser’s address bar. But in the above scenario,we need to redirect the browser to “https” which means that “Hypertext Transfer Protocol over Secure Socket Layer”.
Ok let’s see a real example, type “http://www.gmail.com” in browser after a while the “http” gets converted to “https” in address bar, which means this site is transferring the data over SSL protocal.
How to redirect the browser to https when site is using http protocal in PHP?
First of all, you should know that SSL must be installed in the server. To redirect the browser to “https” , we must know that the site is using SSL or not at the moment. And for this, there is a server variable in PHP called “HTTPS”. $_SERVER['HTTPS'] returns “on” values when the site is using SSL connection.
Function to redirect the browser to “https” in PHP
function redirectToHTTPS()
{ if($_SERVER['HTTPS']!="on") { $redirect= "https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; header("Location:$redirect");}}Above function is quite simple, you can call the function in that page where you’ve to redirect the browser to “https” .This function will preserver you script file name and query string in browser.
Redirecting whole website to “https” using .htaccess
You can call the above function in each and every page to redirect the browser to “https”. But rather than doing so it will be better to write three line of code in .htaccess file to redirect the whole website to use SSL connection throughout the pages.
RewriteEngine On
RewriteCond %{HTTPS} !on RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}Just copy and paste the above code in .htaccess file then the whole website will be redirected to “https” when the browser is opened in “http” mode.