Laravel Security In Depth

Share this post
Security Tip: Cryptographically Secure Randomness
larasec.substack.com

Security Tip: Cryptographically Secure Randomness

[Tip#19] Because all randomness should be cryptographically secure.

Stephen Rees-Carter
Apr 18
Comment
Share

Greetings friends! Firstly, a huge welcome to our new subscribers1. Thank you so much for your support! 😁 I hope you’re learning a lot about Security and how it can be applied to Laravel development.

This week I wanted to remind you all about using cryptographically secure randomness. It’s something I see developers get wrong all the time in my security audits, and in many cases it can open the door to vulnerabilities in your apps, in ways you don’t expect.

šŸ‘‰ If you’re a free subscriber, please become a paid subscriber to support Laravel Security in Depth. You’ll receive weekly security tips (like this one), and our big monthly In Depth emails. Our next In Depth goes out next week!

šŸ‘‰ I offer Laravel Security Audits, so please reach out if want me to hack you site and audit the security of your Laravel app. I’m currently fully booked until August, so if you want an audit this year, you’ll need to book in soon.


Cryptographically Secure Randomness

Computers are terrible at generating randomness. Give a computer the exact same inputs and it will produce the exact same outputs. If you can figure out the starting point (ā€œseedā€), you can figure out the values. This is a huge problem when you consider that cryptography depends on generating unpredictable random keys. If you can predict the key used to encrypt something, you can decrypt it.

So how do computers get around this? Computers use entropy to help generate randomness, which can be collected from all sorts of sources, including user activity and general noise detected within the hardware. Cloudflare have even taken it a step further, and have an entire wall filled with Lava Lamps which generates a significant amount of entropy for use in cryptography.

Although it’s not truly random, it’s good enough to be considered ā€œcryptographically secureā€2.

This brings us to PHP and Laravel. When we’re generating random values in PHP and Laravel, we always want to be using cryptographically secure randomness - which is actually pretty simple. You just need to use the right methods.

Secure Functions

PHP 7 & 8 includes two cryptographically secure methods by default, which you should always use when you need a random value.

random_int()3 generates random numbers:

$number = random_int($min, $max);

random_bytes()4 generates random bytes, which you can use to generate random strings. Laravel includes the Str::random()5 helper, which uses random_bytes() internally to generate friendly random strings for you:

use Illuminate\Support\Str;
 
$random = Str::random($length);

Unsafe Functions

The following functions are not cryptographically secure and should not be used except when securely is not a concern6:

md5(time())
md5(microtime())
md5($model->id . time())
md5(rand(...).time())
sha1(time())
rand($min, $max)
mt_rand($min, $max)
tempnam(...)
md5(rand($min, $max))
base64_encode(...)
base64_encode(rand(...))
md5(base64_encode(time()))

str_shuffle(...)
shuffle()
array_rand()

All of these can be guessed if the attacker has enough time and motivation, and the time-based ones are absolutely trivial.

Note about shuffle() and array_rand(): they don’t use a cryptographically secure random number, so they aren’t safe for any secure purposes or anything that requires true randomness. There is the possibility that their order can be predilected, and if this is a concern, you need to use a cryptographically secure shuffling method.

Laravel’s Arr::shuffle() uses shuffle() internally, so this advice applies to that too.

1

We’re at 829 (free & paid) subscribers, which I find truly incredible. Now we just gotta hit 1,000. šŸ˜‰ I’m thinking of an adequate way to celebrate hitting that number. Please share LSID to get us there faster!

2

The chances of you replicating the exact inputs to produce the same entropy is practically (although not completely) impossible.

3

https://www.php.net/manual/en/function.random-int.php

4

https://www.php.net/manual/en/function.random-bytes.php

5

https://laravel.com/docs/9.x/helpers#method-str-random

6

I’ve seen every single one of these in use on production systems, and a few more variants on the same theme. It’s incredible how often md5() gets used for something that’s supposed to be secure.

CommentComment
ShareShare

Create your profile

0 subscriptions will be displayed on your profile (edit)

Skip for now

Only paid subscribers can comment on this post

Already a paid subscriber? Sign in

Check your email

For your security, we need to re-authenticate you.

Click the link we sent to , or click here to sign in.

TopNewCommunity

No posts

Ready for more?

Ā© 2022 Stephen Rees-Carter
Privacy āˆ™ Terms āˆ™ Collection notice
Publish on Substack Get the app
SubstackĀ is the home for great writing