<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>funcptr - security</title>
    <subtitle>An engineer&#x27;s technical notebook</subtitle>
    <link rel="self" type="application/atom+xml" href="https://funcptr.net/category/security/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://funcptr.net/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2018-12-24T06:19:52+00:00</updated>
    <id>https://funcptr.net/category/security/atom.xml</id>
    <entry xml:lang="en">
        <title>Change one password</title>
        <published>2018-12-24T06:19:52+00:00</published>
        <updated>2018-12-24T06:19:52+00:00</updated>
        
        <author>
          <name>
            
              Delta Regeer
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://funcptr.net/2018/change-one-password/"/>
        <id>https://funcptr.net/2018/change-one-password/</id>
        
        <content type="html" xml:base="https://funcptr.net/2018/change-one-password/">&lt;p&gt;It is that time of year where security professionals the world over end up
talking with friends and family about security. It will be inevitable, almost
as inevitable as someone wearing a stupid Christmas sweater they are a little
too proud of.&lt;&#x2F;p&gt;
&lt;p&gt;The standard advice we&#x27;ve been giving for years is pretty simple:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Don&#x27;t re-use your passwords across sites&lt;&#x2F;li&gt;
&lt;li&gt;Use a password manager&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Anyone that has done technical support for anyone that isn&#x27;t as familiar with
IT knows well that as soon as you complicate something, you end up getting
twice the calls, even for things that are not your fault; &quot;Well, since you
setup that password thing my printer won&#x27;t print&quot; ...&lt;&#x2F;p&gt;
&lt;p&gt;It is fantastic advice, it is where we should all strive to be, we should all
have password managers and should never re-use passwords.&lt;&#x2F;p&gt;
&lt;p&gt;However let&#x27;s change one single password. Start small.&lt;&#x2F;p&gt;
&lt;p&gt;There is likely to be a single account that is the root of trust for all other
accounts. An email address, either at an ISP somewhere (and maybe this is the
year you get them to switch from that old &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.earthlink.net&#x2F;&quot;&gt;Earthlink&lt;&#x2F;a&gt; email address?) or
more likely a free email provider.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s the account we want to target.&lt;&#x2F;p&gt;
&lt;p&gt;If we can secure the root of trust, the email address that can be used for
password reset emails and for phishing we&#x27;ve already won a large battle.
Individual accounts may still be &quot;vulnerable&quot;, but now we&#x27;ve closed one giant
hole.&lt;&#x2F;p&gt;
&lt;p&gt;After all, we all learn to walk before we learn how to run. This small step can
set the tone for even more and better security later.&lt;&#x2F;p&gt;
&lt;p&gt;Should we go further? Absolutely, identify the primary accounts that are high
risk, as an example:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.facebook.com&quot;&gt;Facebook&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.icloud.com&quot;&gt;Apple iCloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;account.microsoft.com&#x2F;&quot;&gt;Microsoft account&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&quot;&gt;Twitter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Facebook Login&#x2F;Twitter is used across many different websites, Apple&#x27;s iCloud
allows remote wipe of devices, and Microsoft Account is used for access to
local machines and likely to OneDrive and other online accounts storing
personal documents and files.&lt;&#x2F;p&gt;
&lt;p&gt;There are many more that I am missing, those can be next, but even the above
tend to roll back up to a single email address.&lt;&#x2F;p&gt;
&lt;p&gt;There is nothing new under the sun, and password re-use is well known and
ridiculed, even Randall Munroe of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;&quot;&gt;XKCD&lt;&#x2F;a&gt; fame published a comic about
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;792&#x2F;&quot;&gt;password re-use&lt;&#x2F;a&gt; a long time ago, however there is one comic that comes to
mind to help create better passwords:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;936&#x2F;&quot;&gt;correct horse battery staple&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Pick four random words from the English language, create a funny sentence and
you are off to the races. Don&#x27;t use &lt;code&gt;correct horse battery staple&lt;&#x2F;code&gt; as a
password, it&#x27;s a terrible password now, but the idea behind generating such a
password is fantastic.&lt;&#x2F;p&gt;
&lt;p&gt;Just changing one password can increase someones security posture just a little
bit, and who knows, next year you&#x27;ll have received less spam email that can be
traced back to their address book being siphoned off and then abused.&lt;&#x2F;p&gt;
&lt;p&gt;For bonus points, have them sign up for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;haveibeenpwned.com&#x2F;&quot;&gt;&#x27;;--have i been pwned?&lt;&#x2F;a&gt;, now each
time a new service is breached your friends or relatives will get a little bit
of notice, and can get an idea for why different passwords are a necessity
these days, and maybe next year they will ask you to show them how to set up
that password manager so they can be even more secure!&lt;&#x2F;p&gt;
&lt;p&gt;Happy Holidays, and good luck with your IT help desk duties this year,
especially getting that printer driver installed, because lets be honest, we&#x27;ll
get blamed for the broken printer in two months whether we touched it or not.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Tamper proof session cookies and session storage</title>
        <published>2014-06-10T17:09:45+00:00</published>
        <updated>2014-06-10T17:09:45+00:00</updated>
        
        <author>
          <name>
            
              Delta Regeer
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://funcptr.net/2014/secure-cookies-for-secure-session-information/"/>
        <id>https://funcptr.net/2014/secure-cookies-for-secure-session-information/</id>
        
        <content type="html" xml:base="https://funcptr.net/2014/secure-cookies-for-secure-session-information/">&lt;p&gt;As a follow-up to my previous article regarding &lt;a href=&quot;&#x2F;2013&#x2F;user-sessions-and-the-data-to-be-stored&#x2F;&quot;&gt;User sessions, what data
should be stored where?&lt;&#x2F;a&gt;, I wanted to discuss how to store the session, and
how to generate cookies that are tamper proof.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-we-trying-to-accomplish&quot;&gt;What are we trying to accomplish?&lt;&#x2F;h2&gt;
&lt;p&gt;Ultimately we want to be able to have X amount pieces of data that are tied to
a particular user. Unfortunately due the fact that HTTP is a stateless protocol
we have to use cookies. Cookies are small little pieces of data that are
transmitted from the server to the client (generally done once), and then upon
the user coming back to the website they are transmitted from the client to the
server. This allows us to uniquely track a single user across connections to
our website.&lt;&#x2F;p&gt;
&lt;p&gt;If the website allows a user to authenticate and the fact that they are
authenticated is stored in the session, we also want to make sure that we can
aggressively expire a session, if this is possible depends on our session
storage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;session-storage&quot;&gt;Session storage&lt;&#x2F;h2&gt;
&lt;p&gt;There are a multitude of ways to store the session data, but it ultimately
boils down to server-side or client-side. Server-side can be done in Cassandra,
Memcache, Redis or even in a SQL database.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;server-side-storage&quot;&gt;Server-side storage&lt;&#x2F;h3&gt;
&lt;p&gt;The main one that has
been used for years is to use server side storage. Storing a small file on the
servers hard drive that contains the data, and the client is sent a cookie that
contains a unique identifier that is linked to the on-disk storage.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1 =&amp;gt; &#x2F;tmp&#x2F;session_1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2 =&amp;gt; &#x2F;tmp&#x2F;session_2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;N =&amp;gt; &#x2F;tmp&#x2F;session_N&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;easily-expire-sessions&quot;&gt;Easily expire sessions&lt;&#x2F;h4&gt;
&lt;p&gt;The upside to server-side storage is that it is possible for us to very easily
expire a session, simply remove the associated file&#x2F;data that is stored and the
users session has now become invalid.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;client-side-storage&quot;&gt;Client-side storage&lt;&#x2F;h3&gt;
&lt;p&gt;The other method that has recently started being used more to make it easier to
scale the server side is to store session data encoded in base64 in the cookie
itself. In this case there is no unique session ID, and no data is stored
server side.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;expiration-is-more-difficult&quot;&gt;Expiration is more difficult&lt;&#x2F;h4&gt;
&lt;p&gt;The downside to using client-side storage is that there is no way, short of the
expiration on the cookie itself for the website to expire a session. There are
work-arounds, but they all require storing state server-side. A hybrid approach
for example is possible, store a unique ID along with the session data, and
store that unique ID server side, but none of the extra data. Remove the unique
ID server side and if we receive a session that contains a unique ID we don&#x27;t
recognise, we simply clear the session.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;expiration-why-do-i-care&quot;&gt;Expiration, why do I care?&lt;&#x2F;h2&gt;
&lt;p&gt;Being able to easily expire a users sessions allows for extra security
measures. For example in Google Mail it is possible to sign out all other
locations, this forces those other locations to re-authenticate before gaining
access to your account.&lt;&#x2F;p&gt;
&lt;p&gt;This is a good security measure to have, so that if a users cookie is stolen,
or their credentials are compromised upon changing their password all their
sessions are invalidated and an attacker using an old cookie&#x2F;session ID can&#x27;t
continue to wreak havoc on the users account.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cookie-format&quot;&gt;Cookie format&lt;&#x2F;h2&gt;
&lt;p&gt;If we are just storing a session ID, or the full session the cookie should be
hardened so that it can not be tampered with by a client. Even if you are
protecting the cookie using SSL, we still don&#x27;t want to allow a malicious user
to modify the cookie to change the session ID or the session itself.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;signing-your-cookie&quot;&gt;Signing your cookie&lt;&#x2F;h3&gt;
&lt;p&gt;The single best way to make sure your cookie has not been tampered with is to
cryptographically sign your cookie, and upon receiving the cookie from the
client verifying that the signature matches what you are expecting. This is
especially important if you are using client-side storage, because you don&#x27;t
want someone to be able to change the user ID from 950 to 1 and suddenly
impersonate a different user.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;use-an-hmac&quot;&gt;Use an HMAC&lt;&#x2F;h4&gt;
&lt;p&gt;HMAC (Hash-based message authentication code) is an cryptographic construct
that uses a hashing algorithm (SHA-1, SHA-256, SHA-3) to create a MAC (message
authentication code) with a secret key. It is very easy given the secret key
and the original data to create the MAC, but it is very difficult if not
impossible to take the original data, and MAC and get the secret key.&lt;&#x2F;p&gt;
&lt;p&gt;This allows us to do the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data = &amp;quot;Hello World&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mac = HMAC(data, sha256, &amp;quot;SEEKRIT&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our &lt;code&gt;mac&lt;&#x2F;code&gt; would now be equal to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;e655f98cb9b3c02f45576f7906d64b0b7f8731f25a5319c42ca666917aca45a4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we now create our cookie as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cookie = mac + &amp;quot; &amp;quot; + data&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It would look as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cookie = e655f98cb9b3c02f45576f7906d64b0b7f8731f25a5319c42ca666917aca45a4 Hello World&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can then send that to the client that requested the page. Once the client
visits the next page, their browser will send that same cookie back to use. If
we split the mac from the data, we can then do the following operation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cookie = e655f98cb9b3c02f45576f7906d64b0b7f8731f25a5319c42ca666917aca45a4 Hello World&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data = &amp;quot;Hello World&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mac = e655f98cb9b3c02f45576f7906d64b0b7f8731f25a5319c42ca666917aca45a4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mac_verify = HMAC(data, sha256, &amp;quot;SEEKRIT&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mac_verify == mac&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If and only if &lt;code&gt;mac_verify&lt;&#x2F;code&gt; and &lt;code&gt;mac&lt;&#x2F;code&gt; are the same can we be sure that the
cookie has not been tampered with.&lt;&#x2F;p&gt;
&lt;p&gt;This requires that the client is NEVER aware of what we are using as our secret
key. In the above exmaples that is &quot;SEEKRIT&quot;. In your web application you will
be required to make this a configuration variable, and you will have to take
care not to commit that configuration variable to a git repository and upload
it to github (for example).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;do-not-use-a-bare-hash-algorithm&quot;&gt;Do not use a bare hash algorithm&lt;&#x2F;h4&gt;
&lt;p&gt;Using a bare hash algorithm allows for &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Length_extension_attack&quot;&gt;length extension attacks&lt;&#x2F;a&gt; if used
incorrectly, this would allow an attacker to concatenate extra data to the end
of our existing data, modify the &quot;MAC&quot; and the server would accept it.&lt;&#x2F;p&gt;
&lt;p&gt;This construct is thus very dangerous:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data = &amp;quot;Hello World&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;key = &amp;quot;SEEKRIT&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mac = SHA1(key + data)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The following construct is still not recommended, but is not nearly as
dangerous:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D6DEEB; background-color: #011627;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mac = SHA1(data + key)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Due to the key being last, this is not vulnerable to a length extension attack,
however please don&#x27;t do this, instead stick to using an HMAC instead.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;encrypting-session-data&quot;&gt;Encrypting session data&lt;&#x2F;h2&gt;
&lt;p&gt;When using client-side storage, it may be beneficial to encrypt the data to add
an extra layer of security. Even if encrypting the data you need to continue
using a MAC.&lt;&#x2F;p&gt;
&lt;p&gt;Using just encryption will not protect you against decrypting bad data because
an attacker decided to provide invalid data. Signing the cookie data with a MAC
makes sure that the attacker is not able to mess with the ciphertext.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-web-frameworks-languages-doing-by-default&quot;&gt;What are web frameworks&#x2F;languages doing by default?&lt;&#x2F;h2&gt;
&lt;p&gt;I am most familiar with the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.pylonsproject.org&#x2F;projects&#x2F;pyramid&#x2F;about&quot;&gt;Pylons Project&#x27;s Pyramid Web Framework&lt;&#x2F;a&gt;, the
default session implementation that is provided by the project is named
&lt;code&gt;SignedCookieSessionFactory&lt;&#x2F;code&gt;, as the name implies this uses a client-side
cookie to store the session data, which is signed using a secret key that is
provided upon instantiation of the factory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;flask.pocoo.org&#x2F;docs&#x2F;quickstart&#x2F;#sessions&quot;&gt;Flask sessions&lt;&#x2F;a&gt; also uses a signed cookie for client-side session storage.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;api.rubyonrails.org&#x2F;classes&#x2F;ActionDispatch&#x2F;Session&#x2F;CookieStore.html&quot;&gt;Ruby on Rails&lt;&#x2F;a&gt; uses a signed&#x2F;encrypted cookie for client-side session
storage by default.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;php.net&quot;&gt;PHP&lt;&#x2F;a&gt; does not by default sign the session cookie, it does however use
server-side storage for session data by default. However extra security can be
added by installing &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.hardened-php.net&#x2F;suhosin.127.html&quot;&gt;PHP SuHoSin&lt;&#x2F;a&gt; which adds session cookie
encryption&#x2F;signing.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>User sessions, what data should be stored where?</title>
        <published>2013-08-25T13:05:00+00:00</published>
        <updated>2013-08-25T13:05:00+00:00</updated>
        
        <author>
          <name>
            
              Delta Regeer
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://funcptr.net/2013/user-sessions-and-the-data-to-be-stored/"/>
        <id>https://funcptr.net/2013/user-sessions-and-the-data-to-be-stored/</id>
        
        <content type="html" xml:base="https://funcptr.net/2013/user-sessions-and-the-data-to-be-stored/">&lt;p&gt;&lt;em&gt;This article has been updated. For the old version please check
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20130826031727&#x2F;http:&#x2F;&#x2F;funcptr.net&#x2F;2013&#x2F;08&#x2F;25&#x2F;user-sessions,-what-data-should-be-stored-where-&#x2F;&quot;&gt;Archive.org&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A couple of days ago on &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;reddit.com&#x2F;&quot;&gt;reddit.com&lt;&#x2F;a&gt;&#x27;s &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;reddit.com&#x2F;r&#x2F;netsec&#x2F;&quot;&gt;&#x2F;r&#x2F;netsec&lt;&#x2F;a&gt; a poster by the name
of &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;danweber.blogspot.com&#x2F;&quot;&gt;Dan Weber&lt;&#x2F;a&gt; posted what he believed to be an attack on PHP sessions:
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;danweber.blogspot.com&#x2F;2013&#x2F;08&#x2F;hacking-php-sessions-by-running-out-of.html&quot;&gt;Hacking PHP sessions by running out of memory&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;netsec&#x2F;comments&#x2F;1k7khy&#x2F;i_know_its_not_that_hard_but_i_think_i_found_a&#x2F;&quot;&gt;(reddit link)&lt;&#x2F;a&gt;. The way
the &quot;attack&quot; works is as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new session&lt;&#x2F;li&gt;
&lt;li&gt;Assign some new data to the session, in this case a username which is used
to signify that the user is logged in.&lt;&#x2F;li&gt;
&lt;li&gt;Check to verify that the user should be logged in&lt;&#x2F;li&gt;
&lt;li&gt;If the user should not be logged in, destroy the session.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The &quot;attack&quot; would be to run the &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;php.net&#x2F;&quot;&gt;PHP&lt;&#x2F;a&gt; script out of memory on number 3, since
once something is set on the session it is immediately stored, so even if the
user is not supposed to be logged in, they are now logged in since their
session says they are.&lt;&#x2F;p&gt;
&lt;p&gt;I wouldn&#x27;t necessarily call this a PHP hack, this is really just bad practice
in terms of programming, the logic should be reversed.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new session&lt;&#x2F;li&gt;
&lt;li&gt;Verify the user should be logged in&lt;&#x2F;li&gt;
&lt;li&gt;If so, set the session data&lt;&#x2F;li&gt;
&lt;li&gt;If the user should not be logged in, don&#x27;t set the session data&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;That would solve the problem at hand, and now there is no way for the user to
trick the PHP script into believing she is logged in when that is not the case.&lt;&#x2F;p&gt;
&lt;p&gt;However as the discussion went on on Reddit, it became even more clear that
there are no good resources on what you should store in the user session, and
what you shouldn&#x27;t store in the user session. Some of these things may seem
like common knowledge, but sadly this is something every single new person to
programming has to learn on their own.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;some-assumptions&quot;&gt;Some assumptions&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s get this out of the way, this is in no way limited to PHP, but it is the
one I will be using as an example. This can all apply to Ruby (&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;rubyonrails.org&quot;&gt;Ruby on
Rails&lt;&#x2F;a&gt;), Python (&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.pylonsproject.org&quot;&gt;Pyramid&lt;&#x2F;a&gt;) or many other frameworks.&lt;&#x2F;p&gt;
&lt;p&gt;The basic problem is that generally writing to the session is not an atomic
transaction based on the page accessed, so the assumption made in this article
is that when you write to the session it is instantly committed, and there is
no way to roll it back upon failure. If there was, our first example listed
wouldn&#x27;t be able to occur since upon running out of memory at step 3, the
session would have been rolled back and cleaned up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-should-you-store-in-the-users-session&quot;&gt;What should you store in the users session?&lt;&#x2F;h2&gt;
&lt;p&gt;You should only really store anything in the session that if it were made
public it would do very little harm.&lt;&#x2F;p&gt;
&lt;p&gt;Really the list of items to be stored in a session are as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The users unique id (The ID that allows you to retrieve the users
information from storage)&lt;&#x2F;li&gt;
&lt;li&gt;Temporary state (i.e. Flash messages)&lt;&#x2F;li&gt;
&lt;li&gt;CSRF token&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;More importantly, don&#x27;t store permission bits, or group memberships, or
anything that is used to allow&#x2F;deny access to particular resources. You want to
store just enough information that upon a user accessing your site you are able
to retrieve the users information from storage, and based upon that information
from storage you then make decisions such as permissions&#x2F;group memberships.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-is-this-important&quot;&gt;Why is this important?&lt;&#x2F;h3&gt;
&lt;p&gt;One of the things that Dan Weber brought up in the Reddit post was storing the
users permission level and group membership in the session. If your code is
then relying on the session to always contain the right permission level, then
there is no way to expire someones access to the data.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A user logs in&lt;&#x2F;li&gt;
&lt;li&gt;A user gets various permissions, and they are set in the session&lt;&#x2F;li&gt;
&lt;li&gt;The user has been fired from his job, and an administrator removes the
users permissions&lt;&#x2F;li&gt;
&lt;li&gt;Since the user is still logged in, the users permission bits are still
set, and he continues to have access to parts of the site&#x2F;information he
shouldn&#x27;t have access to.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If instead on every page visit we simply pull out the users unique id and
verify the permissions upon access, as soon as the permissions are revoked by
the administrator the user no longer has access to the various resources.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;temporary-state&quot;&gt;Temporary state&lt;&#x2F;h3&gt;
&lt;p&gt;There has to be an easy way to remember something from page visit to page visit
that isn&#x27;t considered detrimental if the information gets lost. One of those
things is flash messages. Flash messages are generally used to provide the user
indication that something has changed, they are shown once and then never
again.&lt;&#x2F;p&gt;
&lt;p&gt;Storing these as session data makes sense. If the flash message gets set,
great, if it doesn&#x27;t get set, it doesn&#x27;t matter. Flash messages are simply a
notification tool, if the user misses them it isn&#x27;t important.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-you-shouldn-t-store-in-the-session&quot;&gt;What you shouldn&#x27;t store in the session&lt;&#x2F;h2&gt;
&lt;p&gt;Definitely don&#x27;t store any kind of permission bits, groups a user is a part of
or anything that would allow the user access that they normally would not be
able to access.&lt;&#x2F;p&gt;
&lt;p&gt;On each page access check what permissions the user has. While it may mean a
little more heavy lifting server side it provides extra security, and the means
to enforce changes in permissions instantly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;good-secure-programming-practices&quot;&gt;Good secure programming practices&lt;&#x2F;h2&gt;
&lt;p&gt;Keep secure programming practices in mind at all times, always consider how the
information you are storing&#x2F;processing is accessed&#x2F;viewed&#x2F;administered. More
importantly think about the access controls that are in place, and how one
could expire access to a particular resource without requiring a co-operative
client.&lt;&#x2F;p&gt;
&lt;p&gt;The ordering of how variables are set, and when they are set are very
important.  &lt;code&gt;$_SESSION[&#x27;isadmin&#x27;] = True&lt;&#x2F;code&gt; at the top of a PHP script, and then
removing it by checking to see if the user is actually an administrator later
on in the script is a bad idea.&lt;&#x2F;p&gt;
&lt;p&gt;Always order your code so that if a failure does occur there is no chance that
a critical section of your code is executed by accident, or that information is
stored in a half-verified state. This is especially important for access
control.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
