In Depth: "Password Generator" Security Audit

[InDepth#12] In November 2022, Steve McDougall published a tutorial called "Creating a Password Generator"... we're going to audit his code!

In Depth: "Password Generator" Security Audit

On November 25th 2022, Steve McDougall published a tutorial on Laravel News entitled “Creating a Password Generator”. As you can imagine, this immediately caught my eye and I had to check it out, and I found a few concerning things…

Now, it’s worth pointing out before we get started that this is tutorial code, designed as a simple example to educate developers about building packages, and for discussing the different structures in use. It also includes the following disclaimer on the post and repository:

Disclaimer. This is not intended for use in a production environment to create your passwords. My use case for this is to actually generate one off use codes such as One Time Pass Codes. This is not the most secure as the list of words is quite small, and will leave you open to a potential dictionary attack.

I reached out and had a good chat to Steve about it, and with his permission, we’re going to conduct a security audit on the tutorial code! The tutorial was supposed to be educational, and we’re putting it to good use, learning more about security and how this package could have been built in a much more secure fashion.

If you’ve got time, go have a read the tutorial and/or the GitHub package, but it’s not required to understand this article. We’ll be working down in the order of the tutorial, and I’ll be quoting the relevant bits here for you. Let’s get started!

Defining the Generator Interface

The tutorial starts out by outlining the generator contract like so:

interface GeneratorContract
    public function generate(): string;
    public function generateSecure(): string;

Which are required to return what the tutorial calls a “memorable” or “secure” password. These methods are supposed to return passwords in the following formats:

flying-fish-swimming-lizard - "memorable"
fly1ng-f1sh-sw1mm1ng-l1z4rd - "secure"

This in my opinion is the first mis-step of the tutorial. I like the use of the term “memorable” for the basic password, it clearly explains it’s use and security level (or lack thereof) but calling the second password "secure" sets high expectations for it’s use, when no real level of security has been added2, and developers who don’t understand the context will often make the wrong assumptions based off naming.