1

The PHP docs on session_name() say:

It should contain only alphanumeric characters; it should be short and descriptive (i.e. for users with enabled cookie warnings). ... The session name can't consist of digits only, at least one letter must be present. Otherwise a new session id is generated every time.

So it's clear you must have something non-numeric in there, but it's not quite clear what characters you can't have. The cookie spec itself denies ()<>@,;:\"/[]?={}, but that still leaves others that might be permitted but are not strictly alphanumeric. This is important because cookie security prefixes use - and _ in names like __Secure-PHPSESSID. So I had a rummage in the PHP source code at the session_name function – but I can't see that it does anything other than check it's a string. In practice, it works fine, but I'd be more comfortable knowing precisely why! For example, this works:

session_name('__Secure-PHPSESSID');
session_start();
$_SESSION['test'] = $_SESSION['test'] . "\n" . rand(0,100);
var_dump($_SESSION);

So what are the actual limits on PHP session names?

Synchro
  • 35,538
  • 15
  • 81
  • 104
  • 1
    It says it right there: "only alphanumeric characters". Just letters and numbers, and not all numbers. – Barmar Oct 22 '20 at 17:10
  • 1
    I know that, it's why I quoted the docs. Please read the question – it works fine with session names containing `-` and `_`, so I want to know **exactly** what the constraints are, not just what the docs say, as these are evidently not necessarily the same thing. – Synchro Oct 22 '20 at 17:11
  • The cookie security doc you link to seems to go further stating "A can be any US-ASCII characters, except control characters, spaces, or tabs. It also must not contain a separator character like the following: ( ) < > @ , ; : \ " / [ ] ? = { }." – Wesley Smith Oct 22 '20 at 17:12
  • 2
    It doesn't enforce the requirement, I think it's just anticipating possible problems that could occur, so it's specifying a conservative requirement. – Barmar Oct 22 '20 at 17:13
  • "I want to know exactly what the constraints are" ... I suggest either testing it thoroughly, or asking the people who wrote it. If the documentation is wrong, perhaps you should let them know. We're not the PHP maintainers – ADyson Oct 22 '20 at 17:14
  • 2
    It's possible that there used to be actual restriction in the code and they never updated the docs. OTOH, they also could be allowing for adding restriction in the code later, and you shouldn't depend on the current implementation. – Barmar Oct 22 '20 at 17:15
  • Yes, that's why I want to know exactly what it is. Guessing isn't good enough. The bigger point is that if you can't reliably use `-` and `_`, it denies PHP the ability to use cookie prefixes, which almost amounts to a security hole by omission. There are people on SO that can read the PHP C source better that I can, that are also PHP internals or at least C coders, which is why there is a `php-internals` tag on this, and why I linked to the source code. – Synchro Oct 22 '20 at 17:19
  • 1
    See [this comment](https://www.php.net/manual/en/function.session-name.php#48415) in the documentation, but it's 15 years old and may be obsolete. – Barmar Oct 22 '20 at 18:38

1 Answers1

0

I got a bit further with this. The rules for a session name are defined in this validation function, which permits [a-zA-Z0-9,-]{1,256} (but not numeric-only). You can have commas and dashes in session names in addition to alphanumerics, so the docs are wrong on that. This function is called from an internal session_create_id function, which triggers a warning if the session name doesn't pass that validation.

Despite this, no warning is triggered when passing in a session name containing _. This is demonstrable:

<?php
ini_set('display_errors', true);
error_reporting(E_ALL);
session_name('__Secure-MySession');
session_start();
if (!array_key_exists('test', $_SESSION)) {
    $_SESSION['test'] = '';
}
$_SESSION['test'] .= "\n" . rand(0,100);

var_dump($_SESSION);
echo session_name();

This works perfectly, triggering no errors or warnings, and shows a growing list of random numbers (showing that the session storage is working and therefore the cookies are too), and the second session_name call with no params shows the session name that we set:

__Secure-MySession

And the HTTP headers show that the script sets a cookie called __Secure-MySession:

Headers showing correct session name in cookie

I also tried naming the session My_Session, just in case PHP looks for explicit __Session- prefix, but that works just fine too. Other characters like # or ( do not trigger an error either; in those cases the session name is URL-encoded, which looks remarkably like this bug that was fixed quite a while ago. As expected, 123, works, but also URL-encodes the comma.

So while this demonstrates that having _ in session names works fine, I can't tell you why. I've asked elsewhere too, and if I find out, I will update this question!

Coincidentally, draft 06 of RFC6265bis expires today.

Community
  • 1
  • 1
Synchro
  • 35,538
  • 15
  • 81
  • 104