# [RFC][VOTE] Add session_create_id() function

- Thread: https://externals.io/message/94989
- Original archive: https://news-web.php.net/php.internals/94989
- Started by Yasuo Ohgaki on 2016-08-10T09:14:40+00:00
- Messages: 39
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/94989.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #94989 — Yasuo Ohgaki — 2016-08-10T09:14:40+00:00

URL: https://externals.io/message/94989#94989

Hi all,

This is RFC for adding `session_create_id()` function.

Session ID string uses special binary to string conversion. Users
should write lengthy and slow code to have the same session ID string
as session module does. It also validates and makes sure generated
session ID string has no collision. (This cannot be done easily by
user script and 3rd party C written save handlers)

https://wiki.php.net/rfc/session-create-id
It requires 2/3 majority to pass.
Vote starts: 2016/08/10  - Vote ends: 2016/08/17 23:59:59 UTC

Thank you for voting!

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #94991 — Marco Pivetta — 2016-08-10T09:31:15+00:00

URL: https://externals.io/message/94989#94991 · In reply to: #94989

Hello,

The RFC mentions "Without `session_create_id()`, user has to implement their
own bin_to_readable() in user land.".
This pretty much makes it clear that a userland implementation is feasible,
and thus it should indeed be implemented in userland when possible.

That's my reasoning for voting "no".

Cheers,


Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/



> Hi all,
>
> This is RFC for adding `session_create_id()` function.
>
> Session ID string uses special binary to string conversion. Users
> should write lengthy and slow code to have the same session ID string
> as session module does. It also validates and makes sure generated
> session ID string has no collision. (This cannot be done easily by
> user script and 3rd party C written save handlers)
>
> https://wiki.php.net/rfc/session-create-id
> It requires 2/3 majority to pass.
> Vote starts: 2016/08/10  - Vote ends: 2016/08/17 23:59:59 UTC
>
> Thank you for voting!
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net

---

## #94995 — Yasuo Ohgaki — 2016-08-10T10:03:59+00:00

URL: https://externals.io/message/94989#94995 · In reply to: #94991

Hi Marco,


> The RFC mentions "Without `session_create_id()`, user has to implement their
> own bin_to_readable() in user land.".
> This pretty much makes it clear that a userland implementation is feasible,
> and thus it should indeed be implemented in userland when possible.
>
> That's my reasoning for voting "no".

Thank you for sharing your idea!

> This pretty much makes it clear that a userland implementation is feasible,
> and thus it should indeed be implemented in userland when possible.

Actually, it's not with C written 3rd party session save handlers.
Properly written save handlers should have internal s_validate_sid()
function to check session ID collisions. User script cannot access to
save handler internals. Therefore, it requires a lot of work if user
try to create session ID properly. i.e. Validate generated session ID
string does not collide.

There is API design issue also.
Let's say we add

string str_bin2readble(string $binary, int $bis_per_char);

then we need

string str_reable2bin(string $readble_bin, int $bis_per_char);

Internal bin_to_reable() function is not designed to reversible, i.e.
It cannot convert $readable_bin to $binary, because it does not care
trailing bits that cannot fit into a char. I need more info these
function to be reversible. i.e.

string str_reable2bin(string $readble_bin, int $bis_per_char, int
$number_of_bits_in_readble_bin);

These APIs do not look good to be usable...

I hope I explained well the reason behind to have `session_create_id()`.

Regards,

P.S. I would like to change `session_regenerate_id()` accept 'prefix',
but it has 1st parameter that I would like to remove in the future.
This is the reason why I didn't change `session_regenerate_id()`. It
requires a lot less user code

session_rengenerate_id('myprefix-');

yet it is safe.

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #94996 — Yasuo Ohgaki — 2016-08-10T10:17:52+00:00

URL: https://externals.io/message/94989#94996 · In reply to: #94995

Hi all,


> It requires a lot less user code
>
> session_rengenerate_id('myprefix-');
>
> yet it is safe.

I forgot to mention important requirement.
It is safe when 'session.use_strict_mode=1'.

Unfortunately, RFC for enabling use_strict_mode by default
https://wiki.php.net/rfc/session-use-strict-mode
is declined.

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95045 — Leigh — 2016-08-11T18:25:22+00:00

URL: https://externals.io/message/94989#95045 · In reply to: #94989

> Hi all,
>
> This is RFC for adding `session_create_id()` function.
>
> Session ID string uses special binary to string conversion. Users
> should write lengthy and slow code to have the same session ID string
> as session module does.


I disagree, this pretty much covers it:

function `session_create_id()`
{
$encoded = base64_encode(random_bytes(32));
// Use same charset as PHP
return rtrim(strtr($encoded, '+/', ',-'), '=');
}

---

## #95051 — Yasuo Ohgaki — 2016-08-11T22:58:43+00:00

URL: https://externals.io/message/94989#95051 · In reply to: #95045

Hi Leigh,


> 
> > […]
>
>
> I disagree, this pretty much covers it:
>
> function `session_create_id()`
> {
> $encoded = base64_encode(random_bytes(random_bytes(32)));
> // Use same charset as PHP
> return rtrim(strtr($encoded, '+/', ',-'), '=');
> }

Thank you for insight!

You've missed to set SID to proper length and SID validation.

function session_create_id(string $prefix)
{
    $encoded = base64_encode(ini_get('session.sid_length')*2);
    // Use same charset as PHP
    $sid = substr(rtrim(strtr($encoded, '+/', ',-'), '='), 0,
                          ini_get('session.sid_length');

    $sid .= $prefix;

    // Now validate SID so that it does not have collisions
    when session is active, connect to database and validate SID
      try to fetch sid
        if sid is not there
          try again to generate SID few times
      if SID validation failed
         fatal error
      return safe SID
   when session is inactive
      return unvalidated SID
}

This is what proposed `session_create_id()` does.
I used pseudo, but it should be easy to imagine it would be lengthy code.

IMHO, mandatory API should be in PHP even if it's easy to implement
and basic API should be in PHP unless it is too easy to be implemented
userland.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95052 — Yasuo Ohgaki — 2016-08-11T23:02:22+00:00

URL: https://externals.io/message/94989#95052 · In reply to: #95051

> if sid is not there

s/if sid is not there/if sid is there/

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95053 — Yasuo Ohgaki — 2016-08-11T23:07:05+00:00

URL: https://externals.io/message/94989#95053 · In reply to: #95051

Hi Leigh,

One more additional info.


> IMHO, mandatory API should be in PHP even if it's easy to implement
> and basic API should be in PHP unless it is too easy to be implemented
> userland.

Session SID validation function should be mandatory for user defined
save handlers. Unless we have ready to use `session_create_id()`, they
have to implement by themselves. Requiring something like

function session_create_id(string $prefix)
{
    $encoded = base64_encode(ini_get('session.sid_length')*2);
    // Use same charset as PHP
    $sid = substr(rtrim(strtr($encoded, '+/', ',-'), '='), 0,
                          ini_get('session.sid_length');

    $sid .= $prefix;

    // Now validate SID so that it does not have collisions
    when session is active, connect to database and validate SID
      try to fetch sid
        if sid is there
          try again to generate SID few times
      if SID validation failed
         fatal error
      return safe SID
   when session is inactive
      return unvalidated SID
}

is not good API design, IMHO.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95054 — Yasuo Ohgaki — 2016-08-11T23:20:22+00:00

URL: https://externals.io/message/94989#95054 · In reply to: #95053

Hi Leigh,


>     $encoded = base64_encode(ini_get('session.sid_length')*2);
>     // Use same charset as PHP
>     $sid = substr(rtrim(strtr($encoded, '+/', ',-'), '='), 0,
>                           ini_get('session.sid_length');

I've missed to handle session.hash_bits_per_character here. There are
people validating SID (used chars and length) via WAF or PHP code.
session.hash_bits_per_character handling is mandatory for such system.

Implementing things properly and precisely is not easy :)

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95057 — Yasuo Ohgaki — 2016-08-12T04:28:06+00:00

URL: https://externals.io/message/94989#95057 · In reply to: #94989

Hi all,


> This is RFC for adding `session_create_id()` function.
>
> Session ID string uses special binary to string conversion. Users
> should write lengthy and slow code to have the same session ID string
> as session module does. It also validates and makes sure generated
> session ID string has no collision. (This cannot be done easily by
> user script and 3rd party C written save handlers)
>
> https://wiki.php.net/rfc/session-create-id
> It requires 2/3 majority to pass.
> Vote starts: 2016/08/10  - Vote ends: 2016/08/17 23:59:59 UTC

I've added discussion section so that new readers do not have to read thread.

https://wiki.php.net/rfc/session-create-id#discussions

Those who are not feeling `session_create_id()` function might not be
needed, please try to write session ID validation enabled (NOTE:
Session ID validation is **mandatory** for session security) user
defined session save handler. Then you'll see why.

Not many people voted yet, but this function is "missing must have API".
Thank you for voting!
https://wiki.php.net/rfc/session-create-id

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95059 — Lester Caine — 2016-08-12T08:01:47+00:00

URL: https://externals.io/message/94989#95059 · In reply to: #95054

> I've missed to handle session.hash_bits_per_character here. There are
> people validating SID (used chars and length) via WAF or PHP code.
> session.hash_bits_per_character handling is mandatory for such system.

Since 'id' is a variable, isn't this just a specialist constraint
applied to that variable ;) The various new hash rules follow the same
pattern. Add a domain of 'session_id' to the variable and that selects
all the right rules to handle it ... yes specialist code generating a
special variable may be more efficient, but if the framework is right
than one can simply adjust the rules on a generic variable to cater for
your own requirements?

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #95061 — Yasuo Ohgaki — 2016-08-12T08:23:53+00:00

URL: https://externals.io/message/94989#95061 · In reply to: #95059

Hi Lester,


> 
> > […]
>
> Since 'id' is a variable, isn't this just a specialist constraint
> applied to that variable ;) The various new hash rules follow the same
> pattern. Add a domain of 'session_id' to the variable and that selects
> all the right rules to handle it ... yes specialist code generating a
> special variable may be more efficient, but if the framework is right
> than one can simply adjust the rules on a generic variable to cater for
> your own requirements?

I don't think it's framework job to do.

See "User land `session_create_id()` is easy" section.
https://wiki.php.net/rfc/session-create-id#discussions

It's not easy nor task for frameworks.

If framework would like to write `session_create_id()` "properly",
framework must access session storage database. Let's say storage is
memcached, then framework must open memcached connection by itself and
perform session ID validation. Let's say storage is PostgreSQL, then
framework must open... the same for every other C written session save
handler.

Clearly, it's not a task for framework, but session module.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95069 — Lester Caine — 2016-08-12T09:12:31+00:00

URL: https://externals.io/message/94989#95069 · In reply to: #95061

> I don't think it's framework job to do.

This was a little 'tongue in cheek' ... my main thought was simply that
you need a variable 'session_id' and other processes may benefit from a
similarly constrained variable, so an intelligent variable could be
envisaged that has the code for creating that value. In any case if the
session code creates the variable, you want to ensure that nothing else
modifies it, so $session_id variable should be read_only and blocked
from accidentally escaping it, so even though it is generated within the
session code it's result needs to follow some rules.

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #95071 — Yasuo Ohgaki — 2016-08-12T09:22:51+00:00

URL: https://externals.io/message/94989#95071 · In reply to: #95069

Hi Lester,


> 
> > […]
>
> This was a little 'tongue in cheek' ... my main thought was simply that
> you need a variable 'session_id' and other processes may benefit from a
> similarly constrained variable, so an intelligent variable could be
> envisaged that has the code for creating that value. In any case if the
> session code creates the variable, you want to ensure that nothing else
> modifies it, so $session_id variable should be read_only and blocked
> from accidentally escaping it, so even though it is generated within the
> session code it's result needs to follow some rules.

I see. I think it's good to have intelligent scalar if costs/overheads
are little.

Anyway, thank you for the comment. There may be people that thinks
 `session_create_id()` should be a part of framework or user code.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95091 — Lester Caine — 2016-08-12T11:13:14+00:00

URL: https://externals.io/message/94989#95091 · In reply to: #95071

> Hi Lester,
> 
> 
> > […]
> 
> I see. I think it's good to have intelligent scalar if costs/overheads
> are little.
> 
> Anyway, thank you for the comment. There may be people that thinks
> `session_create_id()` should be a part of framework or user code.

We are probably on the same sheet. I'd prefer to restore the ADOdb
extension that handled time sensitive code in C but that has not kept
pace with all the other changes to extensions. Everything can be done in
user space but just what would benefit from optimising in C.

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #95100 — Tom Worster — 2016-08-12T18:11:12+00:00

URL: https://externals.io/message/94989#95100 · In reply to: #95051

> Hi Leigh,
>
> 
> > […]
>
> Thank you for insight!
>
> You've missed to set SID to proper length and SID validation.

Replacing `rtrim()` with `substr()` is fixes that.


> function session_create_id(string $prefix)
> {
>     $encoded = base64_encode(ini_get('session.sid_length')*2);

Did you omit `random_bytes()` in this line?


>     // Use same charset as PHP
>     $sid = substr(rtrim(strtr($encoded, '+/', ',-'), '='), 0,
>                           ini_get('session.sid_length');
>
>     $sid .= $prefix;
>
>     // Now validate SID so that it does not have collisions
>     when session is active, connect to database and validate SID
>       try to fetch sid
>         if sid is not there
>           try again to generate SID few times
>       if SID validation failed
>          fatal error
>       return safe SID
>    when session is inactive
>       return unvalidated SID
> }
>
> This is what proposed `session_create_id()` does.
> I used pseudo, but it should be easy to imagine it would be lengthy code.

You don't need to waste time checking for collisions if the SID has a 
random component of sufficient length. 32 random base-64 characters is 
sufficient.

There are lots of purposes for random strings with negligible chance of 
collision. Hence some frameworks provide the function, e.g.
http://www.yiiframework.com/doc-2.0/yii-base-security.html#generateRandomString()-detail 


Only the search of the the session database for collisions seems hard to 
me. But I don't understand why it is needed.

Tom

---

## #95104 — Yasuo Ohgaki — 2016-08-12T20:38:34+00:00

URL: https://externals.io/message/94989#95104 · In reply to: #95100

Hi Tom,


> 
> > […]
>
>
> Replacing `rtrim()` with `substr()` is fixes that.

No.

Base 64 adds padding for extra bytes. The Padding char is "=" and it's
illegal char as SID. Therefore trims is mandatory.

Don't you think it's nice to make "PHP just works" without knowing such details?

>
>
> > […]
>
>
> Did you omit `random_bytes()` in this line?

I don't why I did this :)
I thought I replaced "32" to ini setting.

>
>
> > […]
>
>
> You don't need to waste time checking for collisions if the SID has a random
> component of sufficient length. 32 random base-64 characters is sufficient.
>
> There are lots of purposes for random strings with negligible chance of
> collision. Hence some frameworks provide the function, e.g.
> http://www.yiiframework.com/doc-2.0/yii-base-security.html#generateRandomString()-detail
>
> Only the search of the the session database for collisions seems hard to me.
> But I don't understand why it is needed.

Session ID security is key factor of Web application security. There
is huge difference between 'cannot happen' and 'very rare and almost
cannot happen'. In addition, proving 'very rare and almost cannot
happen' is difficult.

NIST requires SHA2 or better hash for collision sensitive usage. SHA2
has 256 bits or more. We only use 128 bits, i.e. MD5 and
bits_per_character=5 now. (130 bits for 7.1 and later). Therefore, I
don't think collision check is needless. We should have 256 bits
session ID at least which requires 52 chars with 5 bits_per_character.

We know it's relatively easy to check if a PRNG meets NIST
requirement, but requirement fulfillment does not mean PRNG is
generating excellent random. Measuring quality of PRNG is difficult.
(This does not mean we should add low quality entropy such as time and
pid to create SID and hash it. We depends on PRNG security anyway, use
of hash and low quality entropy only makes SID weaker. Thus I proposed
raw PRNG usage for SID)

These things make me think collision detection is mandatory to say
"PHP session is secure".

Anyway, I'm not a cryptographer and just following their advices. I
suggest you do the same.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95117 — Tom Worster — 2016-08-13T15:22:58+00:00

URL: https://externals.io/message/94989#95117 · In reply to: #95104

Hi Yasu,



>Base 64 adds padding for extra bytes. The Padding char is "=" and it's
>illegal char as SID. Therefore trims is mandatory.

substr(base64_encode(random_bytes($n)), 0, $n). There is no "=" in the
value for any $n.


>Don't you think it's nice to make "PHP just works" without knowing such
>details?

Not in this particular instance, no. Anybody that takes on the
responsibility of designing a scheme for session ID generation needs to
know such details. The typical PHP programmer does/should not do such work
because its is difficult and dangerous and because the requirement seldom
arises. PHP should not try to patch up garbage session IDs by rejecting
IDs already in use.


>Session ID security is key factor of Web application security. There
>is huge difference between 'cannot happen' and 'very rare and almost
>cannot happen'. In addition, proving 'very rare and almost cannot
>happen' is difficult.

This is equivalent to saying that `random_bytes()` cannot be trusted as a
CSPRNG.


>NIST requires SHA2 or better hash for collision sensitive usage. SHA2
>has 256 bits or more. We only use 128 bits, i.e. MD5 and
>bits_per_character=5 now. (130 bits for 7.1 and later).

Hashing is not the same problem. It's different in some important ways.



>Therefore, I
>don't think collision check is needless. We should have 256 bits
>session ID at least which requires 52 chars with 5 bits_per_character.

I don't think NIST's hashing recommendations should be the basis for
saying how many random bits PHP session IDs should have. I think we should
make our own calculations from first principles.


>We know it's relatively easy to check if a PRNG meets NIST
>requirement, but requirement fulfillment does not mean PRNG is
>generating excellent random. Measuring quality of PRNG is difficult.
>(This does not mean we should add low quality entropy such as time and
>pid to create SID and hash it. We depends on PRNG security anyway, use
>of hash and low quality entropy only makes SID weaker. Thus I proposed
>raw PRNG usage for SID)

Since 7.0, PHP uses the best available practices to obtain random bytes
from the operating system's CSPRNG. These practices are generally
considered good enough for strong cryptography, which demands as much from
a CSPRNG as PHP sessions.

It doesn't make sense to distrust `random_bytes()` but at the same time
trust the host PHP runs on.


>These things make me think collision detection is mandatory to say
>"PHP session is secure".
>
>Anyway, I'm not a cryptographer and just following their advices. I
>suggest you do the same.

I don't agree with the conclusions you draw from NIST hashing
recommendations.

Tom

---

## #95118 — Tom Worster — 2016-08-13T15:35:39+00:00

URL: https://externals.io/message/94989#95118 · In reply to: #94989

> Hi all,
>
> This is RFC for adding `session_create_id()` function.
>
> Session ID string uses special binary to string conversion. Users
> should write lengthy and slow code to have the same session ID string
> as session module does. It also validates and makes sure generated
> session ID string has no collision. (This cannot be done easily by
> user script and 3rd party C written save handlers)

Rather than argue the details of randomness, I have more basic comments.

1. If an app needs to access session values, it can and should do this 
without indirection through the PHP session ID table.

2. Users should generally let PHP choose random IDs.

3. If PHP is to allow a user to chose its own session IDs, avoiding 
collision is should that user's responsibility.

4. Generating unique unpredictable IDs (without requiring collision 
detection) is a common problem with known and trusted solutions.

Tom

---

## #95127 — Yasuo Ohgaki — 2016-08-14T00:56:36+00:00

URL: https://externals.io/message/94989#95127 · In reply to: #95117

Hi Tom,


> 
>
> > […]
>
> substr(base64_encode(random_bytes($n)), 0, $n). There is no "=" in the
> value for any $n.

Generally speaking, you should consider "=" padding when you use
Base64 encoding.
Refer to https://tools.ietf.org/html/rfc4648#section-8 and relevant sections.

>
>
> > […]
>
> Not in this particular instance, no. Anybody that takes on the
> responsibility of designing a scheme for session ID generation needs to
> know such details. The typical PHP programmer does/should not do such work
> because its is difficult and dangerous and because the requirement seldom
> arises. PHP should not try to patch up garbage session IDs by rejecting
> IDs already in use.

My point of view is "session" (the connection/request state management) should
"just work" without knowing details. My recent session related
proposals accomplish
this objective.

IMO. PHP should be easiest, yet secure, Web application programming language.
I don't see any benefits, but only drawbacks, forcing users "to know session
management details to write secure code" while it is very easy to implement
tham in Session module.

>
>
> > […]
>
> This is equivalent to saying that `random_bytes()` cannot be trusted as a
> CSPRNG.

No. It means we should be careful about CSPRNG randomness.
Therefore, I validate SID.

>
>
> > […]
>
> Hashing is not the same problem. It's different in some important ways.

I'm reading between the line here. Cryptographers considers hash less
256 bits is not longer secure. They think 256 bits or more to avoid
collisions. As you may know,  CSPRNGs use hashes internally.  This
fact makes me think we shouldn't blindly trust CSPRNG return values
less than 256bits.

>
>
>
> > […]
>
> I don't think NIST's hashing recommendations should be the basis for
> saying how many random bits PHP session IDs should have. I think we should
> make our own calculations from first principles.

If you would like to know how many bits (true random bits) required
for secure session ID. Following link is helpful to figure out some
aspect of session ID security.

https://www.owasp.org/index.php/Insufficient_Session-ID_Length

We use 130bits out of CSPRNG radam for PHP 7.1. How many bytes is
required for secure session ID is depends on CSPRNG quality and
measuring CSPRNG quality is difficult.

To avoid collision, all we have to do is validating SID then problem is solved.
(Predictability is different issue)

>
> > […]
>
> Since 7.0, PHP uses the best available practices to obtain random bytes
> from the operating system's CSPRNG. These practices are generally
> considered good enough for strong cryptography, which demands as much from
> a CSPRNG as PHP sessions.
>
> It doesn't make sense to distrust `random_bytes()` but at the same time
> trust the host PHP runs on.

Even serious cryptographers admits difficulty of CSPRNG quality
assurance.  We cannot force OSes to have excellent CSPRNG that will
never have collision for obtained bytes.

>
>
> > […]
>
> I don't agree with the conclusions you draw from NIST hashing
> recommendations.

My proposal is much secure than your proposal. It is clear by logic
described above that my proposal is more secure.

Anyway, if things can done easily by PHP, if it is related to security
and if users can forget about secureness when they stick to normal PHP
usage, PHP should be provided as default feature.

Let user mustn't know session security details! I think this is the
way PHP should go.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95128 — Yasuo Ohgaki — 2016-08-14T01:02:51+00:00

URL: https://externals.io/message/94989#95128 · In reply to: #95118

Hi Tom,


> Rather than argue the details of randomness, I have more basic comments.
>
> 1. If an app needs to access session values, it can and should do this
> without indirection through the PHP session ID table.

I don't get point. Why?

>
> 2. Users should generally let PHP choose random IDs.

I agree.

>
> 3. If PHP is to allow a user to chose its own session IDs, avoiding
> collision is should that user's responsibility.

No. I've already explained why this is difficult. Please read previous mail.
Or try to write session save handler that detects collisions with
memcached, then you'll see why.

>
> 4. Generating unique unpredictable IDs (without requiring collision
> detection) is a common problem with known and trusted solutions.

I agree. It's common because many unique ID generator do not have
centralized database to avoid collisions. In contract, session has
centralized database and it's just a matter of one lookup. (Therefore,
session module should lookup database)

Regards,

P.S. I'll add optimization that eliminates SID validation lookup for
normal operations. You don't have to worry about session performance
if I add this.


--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95130 — Lester Caine — 2016-08-14T08:35:26+00:00

URL: https://externals.io/message/94989#95130 · In reply to: #95127

> IMO. PHP should be easiest, yet secure, Web application programming language.
> I don't see any benefits, but only drawbacks, forcing users "to know session
> management details to write secure code" while it is very easy to implement
> tham in Session module.

Sessions are something I rely on, but have thrown numerous problems over
the years. In my systems they should exist for the duration of a client
being logged into the system and so any problems either end have to be
handled. For that reason I store them in the database so when a client
has to log in again we can clear their last activity and start a new
one. The clients can be carrying out interviews for an hour or more, so
previous 'improvements' that try to clear 'inactive sessions' often lost
MY sort of sessions. Clients are only allowed to log on once so I need
to pick up if they try and start a second session, but I don't believe I
NEED all the complexity of cryptography secure id's? Just ones where I
CAN actually identify the client ... or should I be handling that
separate from the actual session_id ?

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #95138 — Yasuo Ohgaki — 2016-08-14T12:33:55+00:00

URL: https://externals.io/message/94989#95138 · In reply to: #95130

Hi Lester,


> 
> > […]
>
> Sessions are something I rely on, but have thrown numerous problems over
> the years. In my systems they should exist for the duration of a client
> being logged into the system and so any problems either end have to be
> handled. For that reason I store them in the database so when a client
> has to log in again we can clear their last activity and start a new
> one. The clients can be carrying out interviews for an hour or more, so
> previous 'improvements' that try to clear 'inactive sessions' often lost
> MY sort of sessions. Clients are only allowed to log on once so I need
> to pick up if they try and start a second session, but I don't believe I
> NEED all the complexity of cryptography secure id's? Just ones where I
> CAN actually identify the client ... or should I be handling that
> separate from the actual session_id ?

Concept of Session is simple just like transaction. Concept of transaction is
simple but implementation requires complexity to do the job right.

You wouldn't say 'Transaction could be inconsistent under rare unfortunate
situations' probably.

Anyway, session module generates collision free session ID by default. Why
not for API generates new ID? Collision check for new session ID is cheap
because it does not happen for every request, but only when session ID
is regenerated.  In addition, user needs a lot of work and details of
session, including session save handler knowledge to generate collision
free session ID.

If anyone would really like to remove collision check overhead, they should
do it by themselves. Unlike collision free session ID generation, it's very
easy. Users can do

ini_set('session.use_strict_mode', 0);
session_id('my_session_id');
 `session_start()`;

with their own responsibility and risk.

Regards,

P.S. The next step having `session_create_id()` is `session_regenerate_id()`
change. For example, having user ID prefixed session would be just

session_regenerate_id(session_create_id($userid));

Warning: To do things like this safely, user MUST enable use_strict_mode!!

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95144 — Yasuo Ohgaki — 2016-08-14T20:13:59+00:00

URL: https://externals.io/message/94989#95144 · In reply to: #95138

Hi all,

It seems importance of session ID validation that prevents collisions
is not recognized enough.

Brute force session ID hihack risk is described here.
https://www.owasp.org/index.php/Insufficient_Session-ID_Length

The expected number of seconds required to guess a valid session
identifier is given by the equation:

(2^B+1)/(2*A*S)

Where:

B is the number of bits of entropy in the session identifier
A is the number of guesses an attacker can try each second
S is the number of valid session identifiers that are valid and
available to be guessed at any given time

It says

"Now assume a 128 bit session identifier that provides 64 bits of
entropy. With a very large web site, an attacker might try 10,000
guesses per second with 100,000 valid session identifiers available to
be guessed. Given these assumptions, the expected time for an attacker
to successfully guess a valid session identifier is greater than 292
years."

292 years may sounds long enough. However, even though the document
explicitly states "it requires validated session ID", but it is clear
it assumes "session manager that validates session ID".

Let me paraphrase OWASP's document to show why.

"Now assume a 128 bit session identifier that provides 64 bits of
entropy. With a very large web site, legitimate users might creates
10,000 new session ID per second (New and regenerated session) with
10,000,000 valid session identifiers available to be collided. Given
these assumptions, the expected time web system to successfully has
collided identifier is greater than 2 years."

Assumption for security should be pessimistic. OWASP makes pessimistic
assumption for entropy in session ID, probably because proving "CSPRNG
generates good quality of random bytes" is difficult.

10M active session is possible even with relatively small sites
because there are users who use very long session ID life time for
"auto login". 10K new session ID is possible for relatively small
sites also because OWASP recommends session ID regeneration for every
15 minutes.

IMHO, it's nonsense to argue "Session ID collision very rare and
cannot happen", "PHP Session ID safe without collision detection",
etc.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #95145 — Yasuo Ohgaki — 2016-08-14T20:20:35+00:00

URL: https://externals.io/message/94989#95145 · In reply to: #95144

> Let me paraphrase OWASP's document to show why.
>
> "Now assume a 128 bit session identifier that provides 64 bits of
> entropy. With a very large web site, legitimate users might creates
> 10,000 new session ID per second (New and regenerated session) with
> 10,000,000 valid session identifiers available to be collided. Given
> these assumptions, the expected time web system to successfully has
> collided identifier is greater than 2 years."
>
> Assumption for security should be pessimistic. OWASP makes pessimistic
> assumption for entropy in session ID, probably because proving "CSPRNG
> generates good quality of random bytes" is difficult.
>
> 10M active session is possible even with relatively small sites
> because there are users who use very long session ID life time for
> "auto login". 10K new session ID is possible for relatively small
> sites also because OWASP recommends session ID regeneration for every
> 15 minutes.


I forgot to mention that "Session management without timestamp will situation
worse" because `session_regenerate_id()` creates many active sessions by default.
(Please refer to decline RFC  timestamp managed session
https://wiki.php.net/rfc/precise_session_management )

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

Next page: https://externals.io/message/94989.md?page=2
