Magento Session Fixation Workaround
20 Mar 2010, by Lloyd Hazlett
5 Comments · Posted in Magento

    Earlier versions of Magento were susceptible to a form of session fixation vulnerability, which can have quite serious consequences even without anyone trying to exploit it maliciously. Visitors may unwittingly follow a link to a Magento site, and be logged in as another user without performing any actions. This results in multiple visitors sharing a session and causes confusion as they add and remove things from the same cart, and potentially even allows them to view another customer's details and place orders under their account. Luckily the issue has a simple fix in version 1.4 and later, but in this post we'll also detail a precaution that can be taken to guard against this in earlier versions.

    The problem stems from a feature whereby the session ID is passed as a GET parameter when the URL by which the current Magento store is being accessed doesn't match that store's base URL. This feature was designed to support a user freely switching between stores within the one site. However, it is quite common for a site to be accessible by two or more URLs (e.g. domain both with and without www), and links that are generated when accessing the site via any URL that is not the base URL will have a SID parameter included in the query string. If a URL of this form is then distributed to many people through an email campaign, ad link, data feed, or by other means, then they may share the session identified by the SID in the URL for as long as it is valid. The person distributing the URL might have quite innocently stumbled into the URL that includes the SID, for example by directly entering the domain name without the www but where the base URL includes it.

    As a workaround, assuming we have Apache rewrites enabled, then we can use a rewrite to remove the offending SID parameter from the query string altogether. The following rewrite would be used before any rewrites of the request to Magento:

    # Covers the case where there are more parameters that follow SID=XXXX
    # We rewrite the query (foo=bar&)SID=XXXX&(baz=naz) to just foo=bar&baz=naz.
    # The ampersand following the preceding parameters, if they are present, is retained.
    RewriteCond %{QUERY_STRING} ^(.+&)?SID=[w]*&(.+)?$ [NC]
    RewriteRule ^(.*)$ /$1?%1%2 [R=301,L,NE]
    # Covers the case where there are no more parameters follow SID=XXXX
    # We rewrite the query (foo=bar)&SID=XXXX to just foo=bar.
    # The ampersand following the preceding parameters, if they are present, is discarded.
    RewriteCond %{QUERY_STRING} ^((.+)&)?SID=[w]*$ [NC]
    RewriteRule ^(.*)$ /$1?%2 [R=301,L,NE]

    The rewrites handle two cases covering whether there are additional parameters following SID or not. One advantage of this approach is that it requires no modification of the application itself and provides an extra layer of security for your website. It could also conceivably be used for other applications aside from Magento to prevent similar problems.

    To turn the option off in Magento 1.4 and later, set "Use SID on Frontend" to "No" under System → Configuration → Web → Session Validation Settings:

    Note that the rewrite detailed above shouldn't interfere with anything else, and could always be left in place following a 1.4 upgrade to guard against the setting ever accidentally being turned back on.