<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9180342751749531954</id><updated>2011-04-21T17:19:59.376-07:00</updated><category term='meta'/><category term='hello world'/><category term='session fixation'/><category term='escaping output'/><category term='persistent login'/><category term='authentication'/><category term='security'/><category term='source code exposure vulnerability'/><category term='shared hosting'/><category term='input filtering'/><category term='session hijacking'/><category term='impersonation'/><category term='session data exposure vulnerability'/><category term='session data modification vulnerability'/><category term='mission statement'/><title type='text'>PHP Report</title><subtitle type='html'>Trends, Techniques, Tips &amp;amp; Tricks for the PHP Scripting Language</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://php-report.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9180342751749531954.post-1102993305253475352</id><published>2009-03-06T12:39:00.000-08:00</published><updated>2009-03-07T12:45:31.414-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='session fixation'/><category scheme='http://www.blogger.com/atom/ns#' term='session hijacking'/><category scheme='http://www.blogger.com/atom/ns#' term='impersonation'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>PHP Security Basics: Session Hijacking</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm1.static.flickr.com/1/3822966_7732f1b463_m.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 240px; height: 160px;" src="http://farm1.static.flickr.com/1/3822966_7732f1b463_m.jpg" border="0" alt="" /&gt;&lt;/a&gt; In the &lt;a href="http://php-report.blogspot.com/2009/02/php-security-basics-authentication.html"&gt;previous post&lt;/a&gt;, we looked at ways that an attacker can impersonate an authorized user and thereby gain unauthorized privilege escalation.  Beyond credential capture, it is possible for an attacker to exploit the session maintenance mechanism itself in order to participate surreptitiously in a session for which an authorized user has provided legitimate authentication credentials.  That is, it is possible for an attacker to &amp;quot;hijack&amp;quot; the session.&lt;br /&gt;&lt;br /&gt;How does this happen?  Most web applications, including PHP web applications, are built around the hypertext transfer protocol (HTTP).  HTTP is a stateless protocol, meaning that each protocol request and response pair is independent of the others.  That is, by default, sequences of related HTTP requests and responses are not grouped together into sessions, with an associated session context.  This functionality is a bedrock necessity for many web applications, but it is functionality that is added above and beyond the basic protocol.&lt;br /&gt;&lt;br /&gt;Of course, PHP implements session management functionality.  If you use PHP's native session mechanism, the requests and responses are grouped together using a PHP session identifier (&lt;code&gt;PHPSESSID&lt;/code&gt;).  When you call &lt;code&gt;&lt;a href="http://www.php.net/session_start"&gt;session_start&lt;/a&gt;&lt;/code&gt;, PHP checks for a &lt;code&gt;PHPSESSID&lt;/code&gt; variable in the incoming cookie or query string.  If &lt;code&gt;PHPSESSID&lt;/code&gt; exists, the &lt;code&gt;_SESSION&lt;/code&gt; superglobal is populated from the associated session store.  Otherwise, &lt;code&gt;PHPSESSID&lt;/code&gt; is given a value and a new session store is initialized.&lt;br /&gt;&lt;br /&gt;If an attacker can guess the value of the generated &lt;code&gt;PHPSESSID&lt;/code&gt;, she can participate in the session.  For example, if a particular session has a session variable &lt;code&gt;$_SESSION['authenticated']&lt;/code&gt; set to &lt;code&gt;TRUE&lt;/code&gt;, the attacker may be able to interact with the PHP application as an authenticated user.  Thankfully, PHP generates values for &lt;code&gt;PHPSESSID&lt;/code&gt; that are sufficiently random so that simple guessing is impractical.  The remaining options for an attacker are: to set the session identifier to a desired value, or to capture the current session identifier.&lt;br /&gt;&lt;br /&gt;Setting the session identifier to a desired value can be as simple for the attacker as having the victim click on a link like the following:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&amp;lt;a href="http://valuableapp.com/index.php?PHPSESSID=1234"&gt;Click Here&amp;lt;/a&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;That is, if no PHP session has been initiated for a particular user at a particular site, the attacker can specify the PHP session identifier by specifying the &lt;code&gt;PHPSESSID&lt;/code&gt; in a cookie or the query string.  This behavior is clearly not desirable.  How can it be prevented?  Session fixation attacks (as such attacks are known) cannot be prevented &lt;em&gt;per se&lt;/em&gt; without modifying PHP's default session management behavior.  However, judicious use of &lt;code&gt;&lt;a href="http://www.php.net/session_regenerate_id"&gt;session_regenerate_id&lt;/a&gt;&lt;/code&gt; can make the attack impractical.&lt;br /&gt;&lt;br /&gt;First note that attacker knowledge of the session identifier isn't (or rather, shouldn't be) particularly problematic until the legitimate user authenticates.  Consequently, regenerating the session identifier following each authentication and/or privilege escalation should be sufficient to prevent impersonation.  The following code illustrates:&lt;pre name="code" class="PHP"&gt;&lt;br /&gt;$_SESSION['authenticated'] = FALSE;&lt;br /&gt;if (authenticate_user()) &lt;br /&gt;{&lt;br /&gt;   session_regenerate_id();&lt;br /&gt;   $_SESSION['authenticated'] = TRUE;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;There remains the risk of session identifier capture.  The &lt;code&gt;PHPSESSID&lt;/code&gt; variable should be propagated between requests using a cookie.  The risk of cookie data exposure can be reduced by following &lt;a href="http://php-report.blogspot.com/2009/02/php-security-basics-golden-rules.html"&gt;the golden rules&lt;/a&gt;, and using SSL encryption.  A useful additional anti-impersonation measure is to store the &lt;code&gt;HTTP_USER_AGENT&lt;/code&gt; value (or, rather, a hash thereof) in the &lt;code&gt;_SESSION&lt;/code&gt; superglobal and require reauthentication should it change during the session.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;font size="0.8em"&gt;Image credit: &lt;a href="http://www.flickr.com/photos/aquilaonline/"&gt;Aquila&lt;/a&gt;&lt;/font&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9180342751749531954-1102993305253475352?l=php-report.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-report.blogspot.com/feeds/1102993305253475352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://php-report.blogspot.com/2009/03/php-security-basics-session-hijacking.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/1102993305253475352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/1102993305253475352'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/2009/03/php-security-basics-session-hijacking.html' title='PHP Security Basics: Session Hijacking'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm1.static.flickr.com/1/3822966_7732f1b463_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9180342751749531954.post-1930246110548661401</id><published>2009-02-28T09:44:00.000-08:00</published><updated>2009-02-28T12:14:50.868-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='impersonation'/><category scheme='http://www.blogger.com/atom/ns#' term='persistent login'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='authentication'/><title type='text'>PHP Security Basics: Authentication</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm1.static.flickr.com/28/59639965_2488a7025b_m.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 179px; height: 240px;" src="http://farm1.static.flickr.com/28/59639965_2488a7025b_m.jpg" border="0" alt="" /&gt;&lt;/a&gt; In order to customize a user's application experience, it is common to create a user account and require that the user login or authenticate in order to gain access to the account.  Such customization is undoubtedly useful, perhaps even central to application functionality.  However, it immediately creates privacy issues and, where elevated access privileges are granted to certain users, it also creates security issues.  Where elevated privileges enable access to valuable resources, attackers will attempt impersonation.&lt;br /&gt;&lt;br /&gt;So, how can we prevent impersonation?  There are two main attack strategies: credential capture and post-authentication session hijacking.  We'll look at session hijacking next post.  Credential capture can take a number of forms.  Simple guessing can usually be defeated by enforcing a delay between login attempts, and the recent practice of adding a captcha after every n&lt;sup&gt;th&lt;/sup&gt; failed attempt is a wise practice to adopt.  SSL encryption is the best defense against password sniffing.  At one time, there wouldn't have been a whole lot more to say as part of a &amp;quot;basics&amp;quot; discussion, however today, persistent login has become a common user expectation.&lt;br /&gt;&lt;br /&gt;A persistent login is simply the persistence of authentication across multiple sessions.  That is, requiring reauthentication only for privilege escalation (as well as financial transactions, etc.) or after some extended period of time has passed (typically seven to fourteen days).  Of course, cookies are the only method of persisting information between sessions, so persistent logins are implemented with a cookie that, at least temporarily, plays the role of authentication credentials.  Improperly implemented, this can be a security disaster.  In particular, storing a user's username and password in the cookie is a critical security breach.&lt;br /&gt;&lt;br /&gt;So what is the secure way to implement persistent login?  Well, there isn't a secure way to implement persistent login, but there are ways that are more secure than others.  Best practice is to create an identifier corresponding to the username specifically for the authentication cookie, as well as a one-time authentication token that takes the place of the password, using code like the following:&lt;pre name="code" class="PHP"&gt;&lt;br /&gt;$salt = 'mysalt'; /* replace mysalt with a string unique to your app */&lt;br /&gt;$persist_user_id = md5($salt . md5($username . $salt));&lt;br /&gt;$persist_auth_token = md5(uniqid(rand(), TRUE));&lt;br /&gt;&lt;/pre&gt;Make sure you enforce persistent login timeouts &lt;em&gt;on the server&lt;/em&gt;, and regenerate the one-time token after every successful authentication (i.e., make sure that it is a &lt;em&gt;one-time&lt;/em&gt; token).  If a user explicitly logs out, be sure to explicitly &amp;quot;delete&amp;quot; the authentication cookie by setting its value to &lt;code&gt;deleted&lt;/code&gt; or the like.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;font size="0.8em"&gt;Image credit: &lt;a href="http://www.flickr.com/photos/tomswift/"&gt;tomswift46&lt;/a&gt;&lt;/font&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9180342751749531954-1930246110548661401?l=php-report.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-report.blogspot.com/feeds/1930246110548661401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://php-report.blogspot.com/2009/02/php-security-basics-authentication.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/1930246110548661401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/1930246110548661401'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/2009/02/php-security-basics-authentication.html' title='PHP Security Basics: Authentication'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm1.static.flickr.com/28/59639965_2488a7025b_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9180342751749531954.post-2923692988821963619</id><published>2009-02-24T11:57:00.000-08:00</published><updated>2009-02-26T21:27:40.009-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='input filtering'/><category scheme='http://www.blogger.com/atom/ns#' term='escaping output'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>PHP Security Basics: The Golden Rules</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm3.static.flickr.com/2205/2307596484_9753b4e39e_m.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 240px; height: 156px;" src="http://farm3.static.flickr.com/2205/2307596484_9753b4e39e_m.jpg" border="0" alt="" /&gt;&lt;/a&gt; &lt;span style="font-weight:bold;"&gt;Filter input.  Escape output.&lt;/span&gt;  You've heard it before, and you'll certainly hear it again.  The reason is that rigorous application of these two rules can eliminate 80% of PHP security issues.  There is a little bit of a culture clash here.  One of the early attractions of PHP were features like &lt;code&gt;register_globals&lt;/code&gt;, that did away with masses of parsing code.  But our collective innocence has been lost.  The &lt;code&gt;register_globals&lt;/code&gt; directive has been set &lt;code&gt;Off&lt;/code&gt; as a default since PHP version 4.2.0 and should remain that way.  There is a lesson here.  Explicit filtering of input is a habit that serious web application developers must adopt.  If your application provides any value at all, attackers will try to exploit any holes you leave.&lt;br /&gt;&lt;br /&gt;So what is input and what is filtering?  Input is any incoming data that may be manipulated by an attacker.  Obviously data coming from the client qualifies as input, e.g., data accessible via the &lt;code&gt;_GET&lt;/code&gt; or &lt;code&gt;_POST&lt;/code&gt; superglobals.  (You may not trust client-side Javascript code, since it is trivially bypassed).  Less obviously, several elements of the &lt;code&gt;_SERVER&lt;/code&gt; superglobal can be set by the client.  In fact, it is a good idea to consider the entire &lt;code&gt;_SERVER&lt;/code&gt; superglobal array as input requiring filtering.  Certainly files read from the filesystem should be considered input.  Should data coming from the database be considered as input?  While the rigorous answer is &amp;quot;yes&amp;quot;, particularly if the database server is located remotely from the web server, for many applications it is not unreasonable to tie application security to database security.  In this case, a judgment call is required.  Such a judgment should be made carefully since it may limit the long term potential of an application.&lt;br /&gt;&lt;br /&gt;Input becomes a PHP variable value.  Input filtering is about ensuring that the variable value conforms to programmatic expectations.  For some types of variable - integers, dates, phone numbers, credit card numbers, email addresses, URLs, etc - these expectations are well defined.  However, part of what makes each application unique is the variable types it defines, implicitly or explicitly, so that input filtering is not as straightforward as it might seem.  In addition, user expectations play a role.  It is safest to require that usernames consist entirely of alphanumeric characters, but many systems also allow underscores, periods and dashes.  More and more systems allow spaces, and disallowing single quotes is sure to annoy the O'Reillys of the world.  It is possible to cater for all these cases.  The point is to set programmatic expectations for variable values, and then ensure that those expectations are met before the variables are used.&lt;br /&gt;&lt;br /&gt;By the way, don't try to modify input so that it conforms with expectations.  This just introduces a layer of complexity that can itself easily result in new security vulnerabilities.  Provide feedback to the application user about input expectations and simply require that they comply.  Again, it is not unwise to enhance application functionality to deal with reasonable input, but once expectations have been set, simply require compliance.&lt;br /&gt;&lt;br /&gt;Escaping output is typically much more straight forward.  Some characters or character sequences have special meaning for the applications to which you send output.  The standard examples are HTML sequences for the client and SQL sequences for the database.  Of course you'll want to send various command sequences to the client and the database, but you'll almost never want the &amp;quot;active&amp;quot; parts of those sequences to come from inside your application variables.  When you do, it should be very explicit, and even then carefully controlled.  For the standard examples, use &lt;code&gt;&lt;a href="http://www.php.net/htmlentities"&gt;htmlentities&lt;/a&gt;&lt;/code&gt; for variables you're sending to the client and the equivalent of &lt;code&gt;&lt;a href="http://www.php.net/mysql_real_escape_string"&gt;mysql_real_escape_string&lt;/a&gt;&lt;/code&gt; for your database.  If your database doesn't have a vendor specific string escape function, you should write one.  Since writing such a function can require considerable research, you can use &lt;code&gt;&lt;a href="http://www.php.net/addslashes"&gt;addslashes&lt;/a&gt;&lt;/code&gt; as a fallback, but you should be aware that you will be vulnerable to vendor specific attacks.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;font size="0.8em"&gt;Image credit: &lt;a href="http://www.flickr.com/photos/piet_musterd/"&gt;Pieter Musterd&lt;/a&gt;&lt;/font&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9180342751749531954-2923692988821963619?l=php-report.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-report.blogspot.com/feeds/2923692988821963619/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://php-report.blogspot.com/2009/02/php-security-basics-golden-rules.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/2923692988821963619'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/2923692988821963619'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/2009/02/php-security-basics-golden-rules.html' title='PHP Security Basics: The Golden Rules'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm3.static.flickr.com/2205/2307596484_9753b4e39e_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9180342751749531954.post-5738440572888477962</id><published>2009-02-22T15:28:00.000-08:00</published><updated>2009-02-24T07:09:05.570-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shared hosting'/><category scheme='http://www.blogger.com/atom/ns#' term='session data modification vulnerability'/><category scheme='http://www.blogger.com/atom/ns#' term='session data exposure vulnerability'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><title type='text'>PHP Security Basics: Shared Hosting (Part 2)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm4.static.flickr.com/3245/2294144289_a54db90ac5_m.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 240px; height: 160px;" src="http://farm4.static.flickr.com/3245/2294144289_a54db90ac5_m.jpg" border="0" alt="" /&gt;&lt;/a&gt; We're discussing PHP specific vulnerabilities that are exacerbated by shared hosting environments.  In the previous post, &lt;a href="http://php-report.blogspot.com/2009/02/php-has-undeservedly-poor-reputation.html"&gt;PHP Security Basics: Shared Hosting (Part 1)&lt;/a&gt;, we discussed a source code exposure vulnerability and mitigation measures.  In this post, we'll look at session data exposure and modification vulnerabilities.&lt;br /&gt;&lt;br /&gt;By default, PHP stores session data as files in &lt;code&gt;/tmp&lt;/code&gt;.  These files have a simple filename structure and the contents can be conveniently decoded with &lt;code&gt;&lt;a href="http://www.php.net/session_decode"&gt;session_decode&lt;/a&gt;&lt;/code&gt;.  Other users on a shared host do not have direct read access to these files, but again, it is possible to co-opt a shared web server into exposing their contents.  In fact, it isn't much of an effort to take the next step and modify the exposed session data, re-encode it with &lt;code&gt;&lt;a href="http://www.php.net/session_encode"&gt;session_encode&lt;/a&gt;&lt;/code&gt; and overwrite the corresponding file in the &lt;code&gt;/tmp&lt;/code&gt; directory.  With this power, an attacker is not far away from giving themselves arbitrary access to your data.&lt;br /&gt;&lt;br /&gt;The solution?  Once again we resort to the database.  That is, using the database as the session data store.  This might seem laborious, but the PHP function &lt;code&gt;&lt;a href="http://www.php.net/session_set_save_handler"&gt;session_set_save_handler&lt;/a&gt;&lt;/code&gt; makes the change fairly painless.  All the actual database interaction should be contained in the six functions supplied to &lt;code&gt;&lt;a href="http://www.php.net/session_set_save_handler"&gt;session_set_save_handler&lt;/a&gt;&lt;/code&gt;.  The &lt;code&gt;_SESSION&lt;/code&gt; variable can then be used in the normal way.  The linked documentation page contains sample code for implementing the required database interaction.&lt;br /&gt;&lt;br /&gt;Yes, storing session data in the database entails a performance hit, but this seems a small price to pay to check a critical security vulnerability in the form of arbitrary session data exposure and modification.  Although most database scalability issues are solvable, in the case that a particular application installation must meet stringent performance requirements, it is likely that a dedicated hosting environment is available.  Such installations always have the option of disabling use of the database as a session data store.  However, use of the database as a session store is a wise default.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;font size="0.8em"&gt;Image credit: &lt;a href="http://www.flickr.com/photos/carbonnyc/"&gt;CarbonNYC&lt;/a&gt;&lt;/font&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9180342751749531954-5738440572888477962?l=php-report.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-report.blogspot.com/feeds/5738440572888477962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://php-report.blogspot.com/2009/02/php-security-basics-shared-hosting-part.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/5738440572888477962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/5738440572888477962'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/2009/02/php-security-basics-shared-hosting-part.html' title='PHP Security Basics: Shared Hosting (Part 2)'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3245/2294144289_a54db90ac5_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9180342751749531954.post-8042554887016061569</id><published>2009-02-21T09:07:00.000-08:00</published><updated>2009-02-24T07:04:40.844-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='shared hosting'/><category scheme='http://www.blogger.com/atom/ns#' term='security'/><category scheme='http://www.blogger.com/atom/ns#' term='source code exposure vulnerability'/><title type='text'>PHP Security Basics: Shared Hosting (Part 1)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm1.static.flickr.com/26/101471354_4d7e293800_m.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 240px; height: 160px;" src="http://farm1.static.flickr.com/26/101471354_4d7e293800_m.jpg" border="0" alt="" /&gt;&lt;/a&gt; PHP has an undeservedly poor reputation for security.  While it is true that PHP doesn't force programmers to use secure practices, this is also true of most other programming languages.  PHP programmers should view security as both a challenge and an opportunity.  A challenge because no one except the attacker is happy when sensitive data is exposed.  An opportunity because the ever shifting nature of security threats means that this is not an area that is going to be automated any time soon.  Security is an area for PHP programmers to display skill and build a valuable reputation.&lt;br /&gt;&lt;br /&gt;Server security is a prerequisite for all else, but generally a PHP programmer's responsibility in this area is going to be limited to choosing secure passwords, using ssh and sftp, and using high privilege accounts only when necessary.  That said, programmers developing for mass markets would be wise to keep in mind that their application will likely reside on shared hosting at some point.  The security of shared hosting can range from good to appalling, but it is never going to earn 5 stars.  It is a simple fact that the number and variety of attack vectors are an order of magnitude higher on shared hosting, particularly if the server administrator doesn't take steps to harden the various default installations.&lt;br /&gt;&lt;br /&gt;So what needs to be done to accommodate shared hosting environments?  You probably aren't going to like the answer, so let me scare you a little bit first.  In non-VPS shared hosting environments, you should assume that an attacker has full access to your PHP source code, including any database authentication credentials if, as is typical, you set those in a PHP file.  Of course, even on dedicated servers, your PHP source code should be stored outside the directory tree that is published by the web server, but these files still need to be accessible to the PHP-enabled web server, so in a shared hosting environment, an attacker may be able co-opt the web server into exposing them.  There are hosting-side measures that can be taken to mitigate such risks (chroot comes to mind), but the point is to stay out of the business of predicting or dictating user hosting environment requirements.  Defense-in-depth is never a bad idea either.  Even the best hosting environments can be compromised.  In fact, it is the best hosting environments, along with their high value applications and databases that are most likely to be targeted by an attacker.&lt;br /&gt;&lt;br /&gt;So what's the solution?  There isn't a good solution, but the best option in a shared hosting environment is to store your source code in the database.  And the database authentication credentials?  Again, there isn't a good solution, but the best option is to store the credentials in environment variables that are available only to your instance of the web server.  If you choose this option, you must be quite careful not to make the contents of &lt;code&gt;_SERVER&lt;/code&gt; public, for example, via &lt;code&gt;&lt;a href="http://www.php.net/phpinfo"&gt;phpinfo&lt;/a&gt;&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Even if you're willing to trust hosting-side solutions for this particular vulnerability (i.e., source code exposure), shared hosting also makes your session data vulnerable to exposure and even &lt;em&gt;modification&lt;/em&gt; by an attacker.  We'll look at the problem and solutions next post.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;font size="0.8em"&gt;Image credit: &lt;a href="http://www.flickr.com/photos/b-tal/"&gt;B Tal&lt;/a&gt;&lt;/font&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9180342751749531954-8042554887016061569?l=php-report.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-report.blogspot.com/feeds/8042554887016061569/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://php-report.blogspot.com/2009/02/php-has-undeservedly-poor-reputation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/8042554887016061569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/8042554887016061569'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/2009/02/php-has-undeservedly-poor-reputation.html' title='PHP Security Basics: Shared Hosting (Part 1)'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm1.static.flickr.com/26/101471354_4d7e293800_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9180342751749531954.post-5114494417664883371</id><published>2009-01-03T20:26:00.000-08:00</published><updated>2009-02-21T11:38:15.057-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mission statement'/><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>About</title><content type='html'>The web is everchanging.  What else could be said to be true?  But PHP will achieve its 14th birthday this year.  Deep middle age in internet years.  There can be no denying it.  PHP has become a pillar web application technology.  And while the pillar shows signs of strain, it shows no sign of yielding.  Even without its current momentum, the inherent simplicity of PHP would continue to win it new users.&lt;br /&gt;&lt;br /&gt;PHP deserves its successes, and also its critics.  The goal of &lt;i&gt;PHP Report&lt;/i&gt; is to document both.  Helping you avoid the pitfalls, while taking full advantage of the evolving architectures of the PHP engines.  Along the way, we might also take a behind-the-scenes look or two at just how they make those wonderful web toys.&lt;br /&gt;&lt;br /&gt;Enjoy,&lt;br /&gt;&lt;br /&gt;Richard.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9180342751749531954-5114494417664883371?l=php-report.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/5114494417664883371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/5114494417664883371'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/2009/02/about.html' title='About'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-9180342751749531954.post-5778652708447064946</id><published>2009-01-02T20:13:00.000-08:00</published><updated>2009-02-21T11:37:54.297-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='meta'/><title type='text'>Contact</title><content type='html'>To contact &lt;span style="font-style: italic;"&gt;PHP Report&lt;/span&gt;, please make a comment on this post. &lt;br /&gt;&lt;br /&gt;Comments are moderated.  Comments made to this post will not be published.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9180342751749531954-5778652708447064946?l=php-report.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-report.blogspot.com/feeds/5778652708447064946/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://php-report.blogspot.com/2009/02/contact.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/5778652708447064946'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/5778652708447064946'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/2009/02/contact.html' title='Contact'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9180342751749531954.post-6748729483939490732</id><published>2009-01-01T20:13:00.000-08:00</published><updated>2009-02-21T11:37:30.654-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hello world'/><title type='text'>Hello World</title><content type='html'>&lt;pre name="code" class="PHP"&gt;&lt;br /&gt;  &amp;lt;?php echo '&amp;lt;p&gt;Hello World&amp;lt;/p&gt;'; ?&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9180342751749531954-6748729483939490732?l=php-report.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://php-report.blogspot.com/feeds/6748729483939490732/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://php-report.blogspot.com/2009/02/hello-world_17.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/6748729483939490732'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9180342751749531954/posts/default/6748729483939490732'/><link rel='alternate' type='text/html' href='http://php-report.blogspot.com/2009/02/hello-world_17.html' title='Hello World'/><author><name>PHP Report</name><uri>http://www.blogger.com/profile/11666172755070931634</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
