Session fixation
Web Design & Development Guide
Session fixation
Home | Up
Session fixation attacks attempt to
exploit the vulnerability of a system which allows one person to
fixate (set) another person's
session identifier (SID).
Most session fixation attacks are web based, and most rely on session
identifiers being accepted from
URLs (query string) or POST data.
Attack scenarios
Alice is a nice girl who just wants to use her bank http://unsafe/ .
Unfortunately, Alice is not very security savvy.
Mallory is out to get Alice's money from the bank.
Alice has a reasonable level of trust in Mallory, and will visit links
Mallory sends her.
A simple attack scenario
Straight forward scenario:
- Mallory has determined that
http://unsafe/ accepts any
session identifier, accepts session identifiers from query string and has no
security validation. http://unsafe/ is thus not secure.
- Mallory sends Alice an e-mail: "Hey, check this out, there is a cool new
account summary feature on our bank,
http://unsafe/?SID=I_WILL_KNOW_THE_SID ". Mallory is trying to fixate
the SID to I_WILL_KNOW_THE_SID .
- Alice is interested and visits
http://unsafe/?SID=I_WILL_KNOW_THE_SID . The usual log-on screen pops
up, and Alice logs on.
- Mallory visits
http://unsafe/?SID=I_WILL_KNOW_THE_SID and
now has unlimited access to Alice's account.
Attack using server generated SID
A misconception is that servers which only accept server generated session
identifiers are safe from fixation. This is false.
Scenario:
- Mallory visits
http://vulnerable/ and checks which SID is
returned. For example, the server may respond: Set-Cookie:
SID=0D6441FEA4496C2 .
- Mallory is now able to send Alice an e-mail: "Check out this new cool
feature on our bank,
http://vulnerable/?SID=0D6441FEA4496C2 .
- Alice logs on, with fixated session identifier
SID=0D6441FEA4496C2 .
Attacks using cross-site cooking
Another session fixation attack,
cross-site cooking, exploits
browser vulnerabilities. This allows a site http://evil/ to
store cookies on browser in the cookie domain of another server
http://good/ , that is trusted. In order for this attack to succeed there
is no need for any vulnerability within http://good/ , as
http://good/ may assume browser cookie management is secure.
Scenario:
- Mallory sends Alice an e-mail: "Hey, check out this cool site,
http://evil/ ".
- Alice visits
http://evil/ , which will cookie SID
with value I_WILL_KNOW_THE_SID into the domain of
http://good/ .
- Alice then receives an e-mail from from Mallory, "hey check out your
bank account at
http://good/ ".
- When Alice logs on Mallory may use her account using the fixated session
identifier.
Counter-measures
Do not accept session identifiers from GET / POST
variables
Session identifiers in URL (query string, GET variables) or POST variables
are not recommended as it simplifies this attack - it is easy to make links or
forms which sets GET / POST variables.
Additionally, session identifiers (SID) in query string enables other risk /
attack scenarios as well;
- SID is leaked to others servers through the
Referrer
- SID is leaked to other people as users cut & paste "interesting links"
from the address bar into chat, forums, communities etc.
- SID is stored in many places (browser history log, web server log, proxy
logs, ...)
Solution: Store session identifier in HTTP cookie
The session identifier is on most modern systems by default stored in an
HTTP
cookie which has a moderate level of security.
However, session identifiers are often accepted from GET/POST as well on
these standard systems. Browser configuration must be modified in order to
protect against this vulnerability.
For PHP, if you have access to PHP configuration, use this: php.ini:
; Whether to use cookies.
session.use_cookies = 1
; This option enables administrators to make their users invulnerable to
; attacks which involve passing session ids in URLs; defaults to 0.
session.use_only_cookies = 1
Solution: Utilize SSL / TLS Session identifier
When enabling HTTPS security, some system will allow applications to obtain
the SSL / TLS session identifier. Use of the SSL/TLS session identifier is very
secure, but many web development languages do not provide robust built-in
functionality for this.
SSL/TLS session identifier may only be suitable for critical applications
such as large financial sites due to the size of the system. It is however an
issue rarely debated even in security forums.
Regenerate SID on each request
A countermeasure against session fixation is to generate a new session
identifier (SID) on each request. Thus, although attacker may trick a user into
accepting a known SID, the SID will be invalid when attacker attempts to re-use
the SID. Implementation of such a system is simple, as demonstrated by the
following:
- Get previous Session Identifier
OLD_SID from HTTP request.
- If
OLD_SID is null, empty, or no session with SID=OLD_SID
exists, create a new session.
- Generate new session identifier
NEW_SID with a secure
random number generator.
- Let session be identified by SID=
NEW_SID (and no longer by
SID=OLD_SID )
- Transmit new SID to client.
Example:
If Mallory successfully tricks Alice into visiting
http://victim/?SID=I_KNOW_THE_SID , this HTTP request is sent to
victim :
GET /?SID=I_KNOW_THE_SID HTTP/1.1
Host: victim
victim accepts SID=I_KNOW_THE_SID , which is bad.
However, victim is secure because it performs session regeneration.
victim sends the following response:
HTTP/1.1 200 OK
Cookie: SID=3134998145AB331F
Alice will now use SID=3134998145AB331F which is unknown to
Mallory, and SID=I_KNOW_THE_SID is invalid. Mallory is thus
unsuccessful in the session fixation attempt.
Unfortunately session regeneration is not always possible. Known cases where
session regeneration may cause problems include when third party software such
as ActiveX, Java Applets, or browser plugins communicate with the server as
well. Third party software could cause logouts, or the session could be split
into two separate sessions.
Accept only server generated SID
One way to improve security is to not accept session identifiers not
generated by server.
if (!isset($_SESSION['SERVER_GENERATED_SID'])) {
session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
$_SESSION['SERVER_GENERATED_SID'] = true;
xcv
Logout function
A logout function is useful as it allows users to indicate that a session
should not allow further requests. Thus attacks can only be effective while a
session is active.
if (isset($_GET['LOGOUT']))
session_destroy(); // destroy all data in session
Time-out old SIDs
This defense is simple to implement and has the advantage of providing a
measure of protection against unauthorized users accessing an authorized user's
account by using a machine they may have left unattended.
Store a session variable containing a time stamp of the last access made by
that SID. When that SID is next used compare the current timestamp (in PHP you
can get this by using the time() function call) with the one stored in the
session. If the difference is greater than a predefined number, say 5 minutes,
destroy the session. Otherwise, update the session variable with the current
timestamp.
Destroy session if Referrer is suspicious
When visiting a page, most browsers will set the
Referrer -
from which page did you click to get to this page?
When using a site which you are logged into, if the site should rarely be
linked to (e.g., banking websites,
webmails),
and/or the session should not last too long as the user might run into links to
the site, it is usually highly suspicious if the Referrer is not from within the
site.
For example, http://vulnerable/ may employ the following
security check:
if (strpos($_SERVER['HTTP_REFERER'], 'http://vulnerable/') !== 0) {
session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
Verify that additional information is consistent
throughout session
One way to further improve security is to ensure that it appears to be the
same end user (client). This makes it a bit harder to perform session fixation
and other attacks.
IP address
As more and more network begin to conform to
RFC 3704 and other anti-spoofing
practices, IP numbers are more reliable as a "same source" identifier.
Therefore, by verifying that the source IP is consistent throughout a session,
the security of a web site can be improved.
This could be performed in this manner:
if($_SERVER['REMOTE_ADDR'] != $_SESSION['PREV_REMOTEADDR']) {
session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
$_SESSION['PREV_REMOTEADDR'] = $_SERVER['REMOTE_ADDR'];
However, there are some things to consider before employing this approach.
- Several users may share one IP. It is not uncommon that an entire
building shares one IP using
NAT.
- One user may have an inconsistent IP. This is true for users behind some
proxies (such as AOL
customers). It is also true for some mobile / roaming users.
For some sites, the added security outweighs the lack of convenience, and,
for others, it does not.
User Agent
Browsers identify themselves by "User-Agent" HTTP headers. This header does
not normally change during use; it would be extremely suspicious if that were to
happen. A web application might make use of User-Agent detection in attempt to
prevent malicious users from stealing sessions. This is
Security through obscurity, which has its uses, but should not be used as a
single defence.
if ($_SERVER['HTTP_USER_AGENT'] !== $_SESSION['PREV_USERAGENT']) {
session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
$_SESSION['PREV_USERAGENT'] = $_SERVER['HTTP_USER_AGENT'];
Defense in Depth
Defense in depth is to combine several countermeasures. The idea is simple:
if one obstacle is hard to overcome, several obstacles could be very hard to
overcome.
A DiD strategy could involve:
- Enable HTTPS (to protect against other problems)
- Correcting configuration (do not accept external SID, set time-out etc)
- Perform session_regeneration, support log-out, reject illegal referrers,
etc.
The following PHP script demonstrates some such countermeasures put together
in a Defence in Depth manner:
if (strpos($_SERVER['HTTP_REFERER'], 'https://DiD/') !== 0)
session_destroy();
if (isset($_GET['LOGOUT']))
session_destroy();
if ($_SERVER['REMOTE_ADDR'] !== $_SESSION['PREV_REMOTEADDR'])
session_destroy();
if ($_SERVER['HTTP_USER_AGENT'] !== $_SESSION['PREV_USERAGENT'])
session_destroy();
session_regenerate_id(); // generate a new session identifier
$_SESSION['PREV_USERAGENT'] = $_SERVER['HTTP_USER_AGENT'];
$_SESSION['PREV_REMOTEADDR'] = $_SERVER['REMOTE_ADDR'];
See also
External links
Home | Up | Browser exploit | Cross-site cooking | Cross-site request forgery | Cross-site scripting | Cross-zone scripting | Directory traversal | Evil twin (wireless networks) | HTTP response splitting | IDN homograph attack | Referer spoofing | Session fixation | Session poisoning | Website spoofing
Web Design & Development Guide, made by MultiMedia | Websites for sale
This guide is licensed under the GNU
Free Documentation License. It uses material from the Wikipedia.
|