Sessions and security
External links: ยป Session fixation
HTTP session management is core of web security. All of mitigation
should be adopted to make sure session security. Developer should
enable/use applicable settings appropriately.
-
session.cookie_lifetime=0.
0 have special meaning. It tells browsers not to store cookie to
permanent storage. Therefore, when browser is terminated, session
ID cookie is deleted immediately. If developer set other than 0, it may
allow other users to use the session ID. Most applications should
use "0" for this. If auto login feature is required, implement
your own secure auto login feature. Do not use session ID for it.
-
session.use_cookies=On and
session.use_only_cookies=On.
Although HTTP cookie has some problems, cookie is preferred way to
manage session ID. Use only cookies for session ID management when
it is possible. Most applications should use cookie for session
ID.
-
session.use_strict_mode=On.
This prevents session module to use uninitialized session ID. In
other word, session module only accepts valid session ID generated
by session module. It rejects session ID supplied by
users. Session ID injection could be done by cookie injection via
JavaScript permanently or temporarily. When transparent session is
enabled, session ID could be injected via query string or form
parameter. There is no reason to accept user supplied session ID,
most applications must not accept user supplied uninitialized
session ID.
-
session.cookie_httponly=On.
Disallow access to session cookie by JavaScript. This setting
prevents cookies stolen by JavaScript injection. It is possible
to use session ID as CSRF protection key, but this is not
recommended. For example, HTML source may be saved and sent to
other users. Developer should not write session ID in web pages for
better security. Almost all applications must use httponly attribute for
session ID cookie.
-
session.cookie_secure=On.
Allows access to session ID cookie only when protocol is HTTPS. If
your web site is HTTPS only web site, you must enable this
setting. Use of HSTS should be considered for HTTPS only web site.
-
session.gc_maxlifetime=[choose smallest possible].
GC is performed by probability. This setting does not guarantee old
session deletion. Some session save handler modules do not use
this setting. Refer to session save handler documentation for
details. Although developer cannot rely on this setting, setting this
to smallest possible value is recommended. Adjust session.gc_probability
and session.gc_divisor so that
obsolete sessions are deleted by appropriate frequency. If auto login
feature is required, implement your own secure auto login feature.
Do not use long life session ID for it.
-
session.use_trans_sid=Off.
Use of transparent session ID management is not prohibited. You
may use it when it is needed. However, disabling transparent
session ID management would improve general session ID security by
removing possibility of session ID injection and session ID leak.
-
session.referer_check=[your originating URL]
When session.use_trans_sid
is enabled, use of this setting is recommended if it is
possible. It reduces risk of session ID injection. If your site is
http://example.com/, set http://example.com/ to it. Note that when
HTTPS is used, browser will not send referrer header. Browser may
not send referrer header by configuration. Therefore, this setting
is not reliable security measure.
-
session.cache_limiter=nocache.
Make sure HTTP contents are not cached for authenticated
session. Allow caching only when contents is not
private. Otherwise, contents may be exposed. "private" may be used
if HTTP content does not include security sensitive data. Note
that "private" may leave private data cached by shared
clients. "public" may be used only when HTTP content does not
contain any private data at all.
-
session.hash_function="sha256".
Stronger hash function will generates stronger session
ID. Although hash collision is unlikely even with MD5 hash, developers
should use SHA-2 or later hash functions for the task. Developers may
use stronger hashes like sha384 and sha512.
The session module cannot guarantee that the information you store
in a session is only viewed by the user who created the session. You
need to take additional measures to actively protect the confidentiality
of the session, depending on the value associated with it.
Assess the importance of the data carried by your sessions and
deploy additional protections -- this usually comes at a price,
reduced convenience for the user. For example, if you want to
protect users from simple social engineering tactics, you need to
enable session.use_only_cookies. In that case,
cookies must be enabled unconditionally on the user side, or
sessions will not work.
There are several ways to leak an existing session ID to third
parties. A leaked session ID enables the third party to access all
resources which are associated with a specific ID. First, URLs
carrying session IDs. If you link to an external site, the URL
including the session id might be stored in the external site's
referrer logs. Second, a more active attacker might listen to your
network traffic. If it is not encrypted, session IDs will flow in
plain text over the network. The solution here is to implement SSL
on your server and make it mandatory for users. HSTS should be used
for this.
Since PHP 5.5.2, session.use_strict_mode
is available. When it is enabled and save handler module supports
it, uninitialized session ID is rejected and new session ID is
created. This protects attack that force users to use known session
ID. Attacker may paste links or send mail that contains session
ID. e.g. http://example.com/page.php?PHPSESSID=123456789 If session.use_trans_sid is
enabled, victim will start session using attacker provided session
ID. session.use_strict_mode
mitigates the risk.
Even though session.use_strict_mode
mitigates risk of adoptive session management, attacker can force
users to use initialized session ID which is created by
attacker. All attacker has to do is initialize session ID prior to
attack and keep it alive.
Session ID cookie could be set with domain, path, httponly, secure
attributes. There is precedence defined by browsers. By using the
precedence, attacker can set session ID that could be used
permanently. Use of session.use_only_cookies
will not solve this issue. session.use_strict_mode
mitigates this risk. With session.use_strict_mode=On,
uninitialized session ID will not be accepted. Session module
creates new session ID always when session ID is not initialized by
session module. This could result in DoS to victim, but DoS is
better than compromised account.
session.use_strict_mode
is good mitigation, but it is not enough mitigation for
authenticated session. Developer must use
session_regenerate_id() for authentication.
session_regenerate_id() must be called prior to
set authentication information to
$_SESSION. session_regenerate_id() makes sure new
session contains authenticated information stored only in new
session. i.e. Errors during authentication process may save
authenticated flag in old session.
Calling session_regenerate_id() function could
result in personal DoS like use_strict_mode=On. However, DoS is
better than compromised account. Session ID should be regenerated
when user is authenticated at least. Session ID regeneration reduces
risk of stolen session ID, thus is should be called periodically.
Developer should not rely on session ID expiration. Attackers may
access victim's session ID periodically to prevent expiration.
Developers must implement their own expiration feature for old sessions.
Note that session_regenerate_id() does not delete
old session by default. Old authenticated session may be available
for use. If developer would like to prevent old authenticated session to
be used by anyone, developer must destroy session by setting
delete_old_session
to TRUE
. However,
immediate old session deletion has unwanted side effect. Session
could be vanished when there are concurrent connections to web
application and/or network is unstable. Instead of deleting old
session immediately, you may set short term expiration time in
$_SESSION by yourselves. If user accesses to obsolete
session(expired session), deny access to it.
session.use_only_cookies
and proper use of session_regenerate_id() could
cause personal DoS. When this is the case, you may ask users to
remove cookies and warn users that there could be possible security
issues. Attackers may set malicious cookies via vulnerable web
application (i.e. JavaScript injection), vulnerable/malicious
browser plugins, etc.
Developers must not use long life session ID for auto login as it
increases risk of stolen session. Auto login should be implemented
by developer. Use secure one time hash key as auto login key using
cookie. Use secure hash stronger than SHA-2. e.g. SHA-256 or greater
with random data from /dev/urandom or like. If user is not
authenticated, check the one time auto login key is valid or not. If
key is valid, authenticate user and set new secure one time hash
key. Auto login key is long lived authentication key, this key should
be protected as much as possible. Use path/httponly/secure
attributes of cookie to protect. Developer must implement feature that
disables auto login and removes unneeded auto login key cookie for
users.