Discussion - The PHP Session ID is Vulnrable to Brute Force Attack

Hello,

I’m just getting back into PHP since I left it 3 years ago, and while going over sessions again, I noticed that the session key is only 32 bits long. This seems to leave websites susceptible to brute force attacks where the session id can be guessed by a cracker. Using the following equation highlights the apparent problem:

((2^NumberOfBits)+1)/(2NumberOfGuessesPerSecondNumberOfActiveSessionsAtOneTime) = expected number of seconds required to guess a valid session identifier
As defined here: https://www.owasp.org/index.php/Insufficient_Session-ID_Length

[table=“width: 800, align: center”]
[tr] [th]Active Sessions[/th] [th]Seconds to guess with 1000 guesses per second[/th] [th]Represented in Hours[/th] [th]in Days[/th] [th]in Weeks[/th] [th]in Months [/th] [th]in Years [/th] [/tr]
[tr] [td] 1 [/td] [td] 2147483.6 [/td] [td] 35791.4 [/td] [td] 1491.3 [/td] [td] 213.0 [/td] [td] 53.3 [/td] [td] 4.4 [/td] [/tr]
[tr] [td] 2 [/td] [td] 1073741.8 [/td] [td] 17895.7 [/td] [td] 745.7 [/td] [td] 106.5 [/td] [td] 26.6 [/td] [td] 2.2 [/td] [/tr]
[tr] [td] 4 [/td] [td] 536870.9 [/td] [td] 8947.8 [/td] [td] 372.8 [/td] [td] 53.3 [/td] [td] 13.3 [/td] [td] 1.1 [/td] [/tr]
[tr] [td] 8 [/td] [td] 268435.5 [/td] [td] 4473.9 [/td] [td] 186.4 [/td] [td] 26.6 [/td] [td] 6.7 [/td] [td] 0.6 [/td] [/tr]
[tr] [td] 16 [/td] [td] 134217.7 [/td] [td] 2237.0 [/td] [td] 93.2 [/td] [td] 13.3 [/td] [td] 3.3 [/td] [td] 0.3 [/td] [/tr]
[tr] [td] 32 [/td] [td] 67108.9 [/td] [td] 1118.5 [/td] [td] 46.6 [/td] [td] 6.7 [/td] [td] 1.7 [/td] [td] 0.1 [/td] [/tr]
[tr] [td] 64 [/td] [td] 33554.4 [/td] [td] 559.2 [/td] [td] 23.3 [/td] [td] 3.3 [/td] [td] 0.8 [/td] [td] 0.1 [/td] [/tr]
[tr] [td] 128 [/td] [td] 16777.2 [/td] [td] 279.6 [/td] [td] 11.7 [/td] [td] 1.7 [/td] [td] 0.4 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 256 [/td] [td] 8388.6 [/td] [td] 139.8 [/td] [td] 5.8 [/td] [td] 0.8 [/td] [td] 0.2 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 512 [/td] [td] 4194.3 [/td] [td] 69.9 [/td] [td] 2.9 [/td] [td] 0.4 [/td] [td] 0.1 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 1024 [/td] [td] 2097.2 [/td] [td] 35.0 [/td] [td] 1.5 [/td] [td] 0.2 [/td] [td] 0.1 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 2048 [/td] [td] 1048.6 [/td] [td] 17.5 [/td] [td] 0.7 [/td] [td] 0.1 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 4096 [/td] [td] 524.3 [/td] [td] 8.7 [/td] [td] 0.4 [/td] [td] 0.1 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 8192 [/td] [td] 262.1 [/td] [td] 4.4 [/td] [td] 0.2 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 16384 [/td] [td] 131.1 [/td] [td] 2.2 [/td] [td] 0.1 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 32768 [/td] [td] 65.5 [/td] [td] 1.1 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 65536 [/td] [td] 32.8 [/td] [td] 0.5 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 131072 [/td] [td] 16.4 [/td] [td] 0.3 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 262144 [/td] [td] 8.2 [/td] [td] 0.1 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 524288 [/td] [td] 4.1 [/td] [td] 0.1 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 1048576 [/td] [td] 2.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]
[tr] [td] 2097152 [/td] [td] 1.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [td] 0.0 [/td] [/tr]

[/table]

I’m guessing the security community are already well aware of this, as a result, is there an easy fix other than not using native PHP sessions?

I’m interested to see what people think about this.

Thanks,
ro0bear :slight_smile:

Just realised, the forum where I read that it was 32 bits long was wrong, he meant 32 bytes long, or 128 bits.

The same table as in the original post except using 128 bits instead of 32 and ignoring seconds, days, weeks, and months is the following:

[table=“width: 500, align: center”]
[tr] [td]Active Sessions[/td] [td]Years to guess with 1000 guesses per second[/td] [/tr]
[tr] [td] 1 [/td] [td] 351647617932517000000000000000.0 [/td] [/tr]
[tr] [td] 2 [/td] [td] 175823808966259000000000000000.0 [/td] [/tr]
[tr] [td] 4 [/td] [td] 87911904483129400000000000000.0 [/td] [/tr]
[tr] [td] 8 [/td] [td] 43955952241564700000000000000.0 [/td] [/tr]
[tr] [td] 16 [/td] [td] 21977976120782300000000000000.0 [/td] [/tr]
[tr] [td] 32 [/td] [td] 10988988060391200000000000000.0 [/td] [/tr]
[tr] [td] 64 [/td] [td] 5494494030195580000000000000.0 [/td] [/tr]
[tr] [td] 128 [/td] [td] 2747247015097790000000000000.0 [/td] [/tr]
[tr] [td] 256 [/td] [td] 1373623507548900000000000000.0 [/td] [/tr]
[tr] [td] 512 [/td] [td] 686811753774448000000000000.0 [/td] [/tr]
[tr] [td] 1024 [/td] [td] 343405876887224000000000000.0 [/td] [/tr]
[tr] [td] 2048 [/td] [td] 171702938443612000000000000.0 [/td] [/tr]
[tr] [td] 4096 [/td] [td] 85851469221806000000000000.0 [/td] [/tr]
[tr] [td] 8192 [/td] [td] 42925734610903000000000000.0 [/td] [/tr]
[tr] [td] 16384 [/td] [td] 21462867305451500000000000.0 [/td] [/tr]
[tr] [td] 32768 [/td] [td] 10731433652725800000000000.0 [/td] [/tr]
[tr] [td] 65536 [/td] [td] 5365716826362880000000000.0 [/td] [/tr]
[tr] [td] 131072 [/td] [td] 2682858413181440000000000.0 [/td] [/tr]
[tr] [td] 262144 [/td] [td] 1341429206590720000000000.0 [/td] [/tr]
[tr] [td] 524288 [/td] [td] 670714603295359000000000.0 [/td] [/tr]
[tr] [td] 1048576 [/td] [td] 335357301647680000000000.0 [/td] [/tr]
[tr] [td] 2097152 [/td] [td] 167678650823840000000000.0 [/td] [/tr]
[/table]
Much safer! :stuck_out_tongue:

Here are some settings from php.ini that will help make the Session ID a lot stronger: (Entropy length and file are the most important, depending on the system they will use a CSPRNG)


; How many bytes to read from the file.
; http://php.net/session.entropy-length
session.entropy_length = 1024


; Specified here to create the session id.
; http://php.net/session.entropy-file
; Defaults to /dev/urandom
; On systems that don't have /dev/urandom but do have /dev/arandom,
; this will default to /dev/arandom
; If neither are found at compile time, the default is no entropy file.
; On windows, setting the entropy_length setting will activate the
; Windows random source (using the CryptoAPI)
session.entropy_file = /dev/urandom

; Select a hash function for use in generating session ids.
; Possible Values
;   0  (MD5 128 bits)
;   1  (SHA-1 160 bits)
; This option may also be set to the name of any hash function supported by
; the hash extension. A list of available hashes is returned by the hash_algos()
; function.
; http://php.net/session.hash-function
session.hash_function = 1 ; or sha256 sha512 etc


; Define how many bits are stored in each character when converting
; the binary hash data to something readable.
; Possible values:
;   4  (4 bits: 0-9, a-f)
;   5  (5 bits: 0-9, a-v)
;   6  (6 bits: 0-9, a-z, A-Z, "-", ",")
; Default Value: 4
; Development Value: 5
; Production Value: 5
; http://php.net/session.hash-bits-per-character
session.hash_bits_per_character = 6

:tup: