<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Think Vitamin &#187; Robert Hafner</title>
	<atom:link href="http://thinkvitamin.com/author/roberthafner/feed/" rel="self" type="application/rss+xml" />
	<link>http://thinkvitamin.com</link>
	<description>The Web Practitioner&#039;s Blog</description>
	<lastBuildDate>Thu, 09 Feb 2012 16:41:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>How to Create Bulletproof Sessions</title>
		<link>http://thinkvitamin.com/code/how-to-create-bulletproof-sessions/</link>
		<comments>http://thinkvitamin.com/code/how-to-create-bulletproof-sessions/#comments</comments>
		<pubDate>Tue, 01 Sep 2009 06:00:56 +0000</pubDate>
		<dc:creator>Robert Hafner</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=2955</guid>
		<description><![CDATA[In the first part of this series we went over how a cookie works and what can be done to secure them. In this section we&#8217;re going to go over ways to add additional security to the session beyond the cookie itself. By the end of this article we will written our own wrapper class [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://events.carsonified.com/fowa/2009/london/schedule?utm_source=TV&amp;utm_medium=banner&amp;utm_campaign=Kevin%2Band%20Gary%20Show"><img src="http://ryancarson.com/uploads/kevin_gary.png" alt="Kevin and Gary show at FOWA London" /></a></p>
<p>In the first part of this series we went over <a href="http://carsonified.com/blog/dev/how-to-create-totally-secure-cookies">how a cookie works and what can be done to secure them</a>. In this section we&#8217;re going to go over ways to add additional security to the session beyond the cookie itself.</p>
<p>By the end of this article we will written our own wrapper class for &#8220;session_start&#8221; that protects  our session from a number of attacks while taking into account some of the unique challenges presented by modern ajax-heavy websites.</p>
<p><span id="more-2955"></span></p>
<h3>Session Specific Attacks</h3>
<p>Through the use of sessions your identity is maintained as you use a website, and just as in real life identity theft is a concern. By taking over your session an attacker would essentially become you on a website, with access to all of the actions, information and privileges that entails.</p>
<p>The main thing that an attacker needs to steal a session is the session ID. There are three ways an attacker normally goings about doing this, all of which can be protected against but are, by default, completely open.</p>
<ul>
<li>Guess the ID: most session handlers generate ids that make this impractical.</li>
<li>Steal the ID: by using malware, sniffing the network, or exploiting javascript exploits attackers can get the value from the cookie itself.</li>
<li>Set the ID: rather than steal or guess the ID an attacker may try and set it to a value they choose.</li>
</ul>
<h3>Starting the Session</h3>
<p>The default session setup is not at all secure by itself, so we&#8217;re going to create a wrapper to add the security we need. To make this code more portable we&#8217;re going to build it as a static function of a php class called SessionManager.</p>
<p>To begin our sessionStart function is going to set the name cookie options for the session. Like all cookies we&#8217;re going to need to make some decisions about what is going to need access to the session ID. Since these options depend on the application itself lets add arguments we can change based on our specific needs. </p>
<p>For security we can hardcode the &#8220;HttpOnly&#8221; argument, as session ids are often the juiciest target for cross site scripting attacks. </p>
<pre><code>class SessionManager
{
   static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
   {
      // Set the cookie name before we start.
      session_name($name . '_Session');

      // Set the domain to default to the current domain.
      $domain = isset($domain) ? $domain : isset($_SERVER['SERVER_NAME']);

      // Set the default secure value to whether the site is being accessed with SSL
      $https = isset($secure) ? $secure : isset($_SERVER['HTTPS']);

      // Set the cookie settings and start the session
      session_set_cookie_params($limit, $path, $domain, $secure, true);
      session_start();
   }
}</code></pre>
<p>Using the new class is as easy as including it and running one line but additional options can make it more restrictive.</p>
<p><code>SessionManage::sessionStart('InstallationName');<br />
SessionManage::sessionStart('Blog_myBlog', 0, '/myBlog/', 'www.site.com');<br />
SessionManage::sessionStart('Accounts_Bank', 0, '/', 'accounts.bank.com', true);</code></p>
<h3>Lock the Session to a Host</h3>
<p>Now that our wrapper class is in place and functional we can start building in additional security by restricting the session to the same IP address and User Agent (or browser) as when the session was first opened. This way if the session ID is stolen or guessed the attacker still has to get ahold of the user agent (admittedly not too difficult if they got the session ID) and somehow find a way to get the same IP address.</p>
<p>These attacks only help if the user is not on the same network. The user agent check only adds minor security, since many attacks that compromise the cookie are going to do the same to the user agent. If an attacker is on the same network as the target there is a good chance they already have the same external IP address, as it is pretty common for a network to use private internal addresses while presenting only a single IP address to the internet. This is why it is important to evaluate the need for SSL.</p>
<p>We&#8217;re going to add these new checks to our class in the function preventHijacking. This function will return false on new sessions or when a session is loaded by a host with a different IP address or browser. preventHijacking will true if the session is valid and false otherwise. This means it will return false not just on malicious attempts but completely new sessions as well.</p>
<pre><code>static protected function preventHijacking()
{
	if(!isset($_SESSION['IPaddress']) || !isset($_SESSION['userAgent']))
		return false;

	if ($_SESSION['IPaddress'] != $_SERVER['REMOTE_ADDR'])
		return false;

	if( $_SESSION['userAgent'] != $_SERVER['HTTP_USER_AGENT'])
		return false;

	return true;
}</code></pre>
<p>Now that we have a way to identify hijacking attempts we need to set up a way to respond to them. For us this means two things- clearing out the old session data and inserting the IP address and user agent into the new session.</p>
<pre><code>static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
{
	...
	session_start();

	if(!self::preventHijacking())
	{
		$_SESSION = array();
		$_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];
		$_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
	}
}</code></pre>
<h3>Session Fixation</h3>
<p>So far we have effectively eliminated the possibility of brute force guessing. We&#8217;ve also made it so any attempts at capturing the session ID would require the attacker to be on the same network as the user in order to take advantage of that ID, while also discussing enforcing SSL to make capturing the session more difficult through traditional means. However, what if the attacker could set the session ID themselves?</p>
<p>By getting the user to follow a link with a session ID in it the attacker can trick the user into starting a session with the ID of the attacker&#8217;s choosing. Rather than guess or steal an ID the attacker will have it right from the start. Many web environments, including PHP, allow session ids to be set through the URL, primarily to get around systems which do not support cookies. Just like with regular cookies the value sent by the client is the value used for the ID, so in this case the value in the URL becomes the session ID.</p>
<p>The solution to this is to change the session ID. How often you do this is tends to be a matter of great debate, but at the bare minimum the ID should be changed when new sessions are created and when the user changes privileges (logs in or out).</p>
<h3>A First Attempt At Regenerating the ID</h3>
<p>Regenerating the ID is fairly simply in php. Deceptively simple one might say. The function &#8220;session_regenerate_id&#8221; lets us tell the system to use a new ID.  It can also optionally delete the old session.</p>
<pre><code>// Leaves old session intact
session_regenerate_id();

// Deletes old session
session_regenerate_id(true);</code></pre>
<p>If you don&#8217;t delete the old session then it is still vulnerable to hijacking and whatever access it had can be granted to an attacker. If you&#8217;re changing the session ID often without deleting the old ones you could be creating more holes by leaving a trail of old, but valid, sessions.</p>
<h3>Regenerating the ID in the World of Ajax</h3>
<p>If an application creates a lot of quick connections to the server some interesting things can happen. PHP, and many other languages, restricts access to the session data to one running script at a time, so if multiple requests come in that try to access the session data the second request (and any other) gets queued up. When the first request changes the ID and deletes the old session the second request still has the old session ID which no longer exists. This results in a third, new session being opened and generally means your user gets logged out.</p>
<p>This bug is ridiculously hard to diagnose as the timing of not just the requests but the ID regeneration has to be just right. In sites that don&#8217;t make requests to the server using javascript this type of bug may never be encountered at all, as the time between page loads is more than long enough for the browser to have updated its session info. For sites that make use of ajax techniques, however, this issue will have a chance of occurring whenever the session ID is changed.</p>
<p>In our final update to the SessionManager class we&#8217;re going to write a fix for this problem. Rather than delete the session immediately when we change the ID, we&#8217;re going to mark the old session as obsolete and mark it to expire in ten seconds. This way any queued up requests will still have access to the expired session but we don&#8217;t have to leave it open forever.</p>
<p>To accomplish this we&#8217;re going to add the regenerateSession function. This function adds the obsolete flag and expiration to the session, regenerates the ID to create the new session and saves them both. It  then reopens the new session and removes the obsolete flag. Unlike our other internal functions we are leaving this one open for use outside the class so that it can be tied into login scripts.</p>
<pre><code>static function regenerateSession()
{
	// If this session is obsolete it means there already is a new id
	if(isset($_SESSION['OBSOLETE']) || $_SESSION['OBSOLETE'] == true)
		return;

	// Set current session to expire in 10 seconds
	$_SESSION['OBSOLETE'] = true;
	$_SESSION['EXPIRES'] = time() + 10;

	// Create new session without destroying the old one
	session_regenerate_id(false);

	// Grab current session ID and close both sessions to allow other scripts to use them
	$newSession = session_id();
	session_write_close();

	// Set session ID to the new one, and start it back up again
	session_id($newSession);
	session_start();

	// Now we unset the obsolete and expiration values for the session we want to keep
	unset($_SESSION['OBSOLETE']);
	unset($_SESSION['EXPIRES']);
}</code></pre>
<p>We need to add another function to check for the obsolete flag and to see if the session has expired.</p>
<pre><code>static protected function validateSession()
{
	if( isset($_SESSION['OBSOLETE']) &amp;&amp; !isset($_SESSION['EXPIRES']) )
		return false;

	if(isset($_SESSION['EXPIRES']) &amp;&amp; $_SESSION['EXPIRES'] &lt; time())
		return false;

	return true;
}</code></pre>
<p>Finally, in the last change to our SessionManager, we need to update our SessionStart function. It needs to call the regenerateSession function on new requests and periodically after that, as well as destroy the session if it is invalid. Here is the complete SessionStart function.</p>
<pre><code>static function sessionStart($name, $limit = 0, $path = '/', $domain = null, $secure = null)
{
	// Set the cookie name
	session_name($name . '_Session');

	// Set SSL level
	$https = isset($secure) ? $secure : isset($_SERVER['HTTPS']);

	// Set session cookie options
	session_set_cookie_params($limit, $path, $domain, $https, true);
	session_start();

	// Make sure the session hasn't expired, and destroy it if it has
	if(self::validateSession())
	{
		// Check to see if the session is new or a hijacking attempt
		if(!self::preventHijacking())
		{
			// Reset session data and regenerate id
			$_SESSION = array();
			$_SESSION['IPaddress'] = $_SERVER['REMOTE_ADDR'];
			$_SESSION['userAgent'] = $_SERVER['HTTP_USER_AGENT'];
			self::regenerateSession();

		// Give a 5% chance of the session id changing on any request
		}elseif(rand(1, 100) &lt;= 5){
			self::regenerateSession();
		}
	}else{
		$_SESSION = array();
		session_destroy();
		session_start();
	}
}</code></pre>
<h3>Summery</h3>
<p>At times it amazes me how complex something as simple as an ID- what is essentially just a string of random characters- can turn out to be. While you can certainly use this class for all of your own projects here is what you need to remember when building your own session manager.</p>
<p>Session IDs are attacked by guessing, capturing or setting the id. You can protect against this in your own applications by &#8230;</p>
<ul>
<li>Securing the cookie to make stealing the ID harder</li>
<li>Limiting the session to a specific host to make attacks more difficult</li>
<li>Changing the ID when escalating privileges and throughout the session life.</li>
</ul>
<p>Here is the complete <a href="http://ryancarson.com/uploads/securingcookies/Session.class.php.zip">Session.class.php file</a> for your reference.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkvitamin.com/code/how-to-create-bulletproof-sessions/feed/</wfw:commentRss>
		<slash:comments>49</slash:comments>
		</item>
		<item>
		<title>How to Create Totally Secure Cookies</title>
		<link>http://thinkvitamin.com/code/how-to-create-totally-secure-cookies/</link>
		<comments>http://thinkvitamin.com/code/how-to-create-totally-secure-cookies/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 07:00:38 +0000</pubDate>
		<dc:creator>Robert Hafner</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://carsonified.com/?p=2945</guid>
		<description><![CDATA[Securing cookies and sessions is vital to keeping an application secure. Many tutorials have been written on the subject, but as the internet (and browsers loading it) evolve so do the methods you can use to keep your application secure. In this article we&#8217;re going to break down the various components of a cookie and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://events.carsonified.com/fowa/2009/london/schedule?utm_source=TV&amp;utm_medium=banner&amp;utm_campaign=Kevin%2Band%20Gary%20Show"><img src="http://ryancarson.com/uploads/kevin_gary.png" alt="Kevin and Gary show at FOWA London" /></a></p>
<p>Securing cookies and sessions is vital to keeping an application secure. Many tutorials have been written on the subject, but as the internet (and browsers loading it) evolve so do the methods you can use to keep your application secure.</p>
<p>In this article we&#8217;re going to break down the various components of a cookie and what they mean for security. This will include limiting the cookie to certain domains and paths on those domains, choosing what information to store, and protecting the cookie from cross site scripting exploits. In a second article we will go into more depth in how to protect everyone&#8217;s favorite cookie, the session ID.</p>
<p><span id="more-2945"></span></p>
<h3>How Cookies Work</h3>
<p>Cookies are simply key/value pairs that let us get around HTTP being a stateless protocol. When a developer has data they wish to last for more than one connection they can use cookies to store that data on the client side. While this tends to get handled by the programming language being used it is accomplished using HTTP headers.</p>
<p>When the server wants to set a cookie it passes back a header named &#8220;Set-Cookie&#8221; with the key-value pair and some options.</p>
<p><a href="http://ryancarson.com/uploads/securingcookies/bigger-liveheaders-setcookie.png"><img src="http://ryancarson.com/uploads/securingcookies/smaller-liveheaders-setcookie.png" alt="The HTTP server responds with Set-Cookie: Test_Session=f8daa3ad35a272514a18039e8a93b204; path=/; HttpOnly" /></a><br /><a href="http://ryancarson.com/uploads/securingcookies/bigger-liveheaders-setcookie.png">View larger</a></p>
<p>On subsequent requests the client will send along its own header to let the server know the name and value of its stored cookies. The server will not continue to send back the cookies, it will only send them if there is a change.</p>
<p><a href="http://ryancarson.com/uploads/securingcookies/bigger-liveheaders-clientcookie.png"><img src="http://ryancarson.com/uploads/securingcookies/smaller-liveheaders-clientcookie.png" alt="The browser sends the server Set-Cookie: Cookie: Test_Session=f8daa3ad35a272514a18039e8a93b204" /></a><br /><a href="http://ryancarson.com/uploads/securingcookies/bigger-liveheaders-clientcookie.png">View larger</a></p>
<p>You can see all the headers for yourself using the LiveHeaders plugin for Firefox.</p>
<h3>The Problem</h3>
<p>This data is completely in control of the client- it is trivial to change the values of a cookie. That means that, just like post and get data, all cookie data must be validated in some way. At the same time you&#8217;ll want to avoid storing sensitive information, such as passwords, as cookies are stored in cleartext and anyone with access to the computer later can easily pick those up (I know of at least one security forum that was hacked in this way).  It is also important to note that HTTP does not encrypt the headers in any way. If the connection isn&#8217;t over SSL then it will not be protected from snooping eyes.</p>
<p>Session cookies are no different than any other cookie- their value is just a simple ID. Those IDs are susceptible to all of the same limitations as other cookies. The real power behind sessions happens server side, where the ID is used to pull out data stored on the server. This has many benefits over storing data directly into the cookie itself- data can&#8217;t be manipulated by the user, large amount of data can be stored without having to send it back and forth with each request, and you can store data you otherwise wouldn&#8217;t want the client to have access to.</p>
<h3>Getting Started</h3>
<p>The first step towards securing your cookie is to restrict that cookie to only your application. This is especially important in environments that support multiple sites or applications (the type of shared hosting you often see on corporate or university domains). By restricting the cookie to only  the applications that need it you reduce the chances of it being sniffed while also keeping the cookie namespaces clear for other applications that use them.</p>
<p>There are three options that can be sent along when creating a cookie that, when used properly, will keep the cookie limited to only your application. Before setting these options you will need to ask yourself a few questions-</p>
<ul>
<li>What parts of the website need access to the cookie?</li>
<li>Will the cookie need to work across sub domains?</li>
<li>Will the cookie need to persist if the user leaves an SSL portion of the site?</li>
</ul>
<p>There is also a forth option used by newer browsers to restrict access to cookies by javascript.</p>
<p>As you will see, how exactly to restrict the cookie really does depend on the exact purpose for that cookie. A banking or ecommerce site may restrict their cookies to only SSL, while a blog or news aggregator may want to leave things more open.</p>
<h3>Cookie Options</h3>
</p>
<p><b>Send The Cookie To Only Your Application</b></p>
<p>The Path argument specifies what paths on the site to send the cookie. The default value of &#8220;/&#8221; means every request will get the cookie, while &#8220;/forums/&#8221; would limit the cookie to just that path. This path is going to be based on the actual URL the browser uses, before any mod_rewrite or other URL mapping.</p>
<p><b>Don&#8217;t Share With Sub Domains</b></p>
<p>The Domain option allows you to specify whether or not to send the cookie to subdomains. Setting &#8220;www.example.com&#8221; will mean only the exact domain &#8220;www.example.com&#8221; will be matched, while &#8220;.example.com&#8221; will also match again any subdomaim (forums.example.com, blog.example.com).</p>
<p><b>Require a Secure Connection</b></p>
<p>Using the Secure option you can tell the browser (or other http clients) to only send the cookie over SSL connections. This means the cookie will not be available to any part of the site that is not secure will not have access to the cookie, but it also makes it much less likely that you&#8217;ll accidentally send the cookie across as cleartext.</p>
<p><b>Protect Against XSS Exploits</b></p>
<p>This HttpOnly flag is used to tell the browser that it should not allow javascript to access the contents of the cookie. This is primarily a defense against cross site scripting, as it will prevent hackers from being able to retrieve and use the session  through such an attack.</p>
<p>The HttpOnly option is not by any means full proof. As a client-side defense mechanism it relies on browser support to work, but is only supported by a few browsers (Firefox 3+ and IE 7+, with partial support from Opera 9.5, IE6 and Chrome).</p>
<h3>Configuring the Cookie</h3>
<p>In PHP, setting the arguments for cookies is done through some optional arguments on the &#8220;setcookie&#8221; function:</p>
<pre><code>setcookie( name, value, expire, path, domain, secure, httponly);

// Open
setcookie( 'UserName', 'Bob', 0, '/', '.example', false, false);

// Locked Down
setcookie( 'UserName', 'Bob', 0, '/forums', 'www.example.com', isset($_SERVER["HTTPS"]), true);</code></pre>
<p>To change the cookie values for the session cookie requires the &#8220;session_set_cookie_params&#8221; function, which needs to be called before the session is started.</p>
<pre><code>session_set_cookie_params($expire, $path, $domain, $secure, true);

// Open
session_set_cookie_params(0, '/', '.example', false, false);

// Locked Down
session_set_cookie_params('o, /forums', 'www.example.com', isset($_SERVER["HTTPS"]), true)</code></pre>
<h3>Summary</h3>
<p>Cookies remain the basic method of identify tracking on most websites and keeping them secure is a vital part to keeping applications as a whole locked down and secure. In this article we went over four methods for protecting cookies on a general level.</p>
<p>When using cookies its important to remember to:</p>
<ul>
<li>Limit the amount of sensitive information stored in the cookie.</li>
<li>Limit the subdomains and paths to prevent interception by another application.</li>
<li>Enforce SSL so the cookie isn&#8217;t sent in cleartext.</li>
<li>Make the cookie HttpOnly so its not accessible to javascript.</li>
</ul>
<p>Please check out the second half of this series, where we&#8217;re going to take the next step with an in depth guide to securing sessions.</p>
]]></content:encoded>
			<wfw:commentRss>http://thinkvitamin.com/code/how-to-create-totally-secure-cookies/feed/</wfw:commentRss>
		<slash:comments>41</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.306 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-11 16:41:51 -->

