Securing Laravel

Share this post

Security Tip: Test for Missing Authorisation

securinglaravel.com

Discover more from Securing Laravel

The essential security resource for Laravel devs, covering everything you need to keep your apps secure. Sign up to receive weekly security tips and monthly in depth articles, diving deep into security concepts you need to know!
Over 2,000 subscribers
Continue reading
Sign in

Security Tip: Test for Missing Authorisation

[Tip#48] We write tests for everything else, so why not write tests for authorisation as well?

Stephen Rees-Carter
Jun 10, 2023
4
Share this post

Security Tip: Test for Missing Authorisation

securinglaravel.com
5
Share

Greetings friends! The second most common security issue I discover when doing security audits on Laravel apps is… Missing Authorisation! I was honestly surprised to see it so high - Laravel has many robust and well-known authorisation tools, but the numbers didn’t lie. As I dug into it, I realised it most commonly occurs on a single route, due to a single `authorize()` call being missed in a controller action. I’ve covered many of Laravel’s authorisation features before, but for Today’s tip we’re focusing on a very specific idea that will help you avoid this exact problem.

Here’s our current Top 10:
#10 → Insufficient Input Validation
#9 → Missing Subresource Integrity (SRI)
#8 → Insufficient Rate Limiting
#7 → Cross-Site Scripting (XSS)
#6 → Outdated & Vulnerable Dependencies
#5 → Insecure Function Use
#4 → Missing Security Headers
#3 → Missing Content Security Policy (CSP)
#2 → Missing Authorisation

🛡️ When was your last annual security audit?
🕵️ Book a security audit now!

Looking to learn more?
⏩ OWASP Security Tip: A06:2021 – Vulnerable and Outdated Components
▶️ OWASP In Depth: A05:2021 – Security Misconfiguration


Securing Laravel is 100% reader-supported. Please consider becoming a free or paid subscribe to receive new posts and support my security work in the Laravel community!


Test for Missing Authorisation

In my experience auditing Laravel apps, the most common cause for missing authorisation is due to the developer forgetting to include an `authorize()` call within a controller action. It’s far less common to forget when authorisation is handled within the routes file1, but it can be easily missed in there too, so I’m talking to everyone here!

Forgetting authorisation is super easy to do - you’re adding your route, writing your controller action, thinking about the logic, where the inputs go, the validation rules you need, which jobs and events are dispatched, and what is returned to the browser. But somewhere in there you’ve forgotten to check if the user has permissions to actually do any of it…

So how do we avoid this trap? Write tests that specifically check for permissions, alongside your feature and unit tests!

If you think about it, it makes perfect sense. We write tests that cover the success and failure states of our features - ensuring everything works as expected, and nothing is broken accidently in the future. So we really should be writing tests that check we’ve implemented authorisation correctly, and that it doesn’t break in the future.

When I’m writing tests, I try to hit each of these use cases2:

  • Guest request

  • Not allowed user request

  • Allowed user request

I typically use one of these assertions in my tests3:

$this->assertStatus($status);
$this->assertUnauthorized(); // 401
$this->assertForbidden();    // 403
$this->assertNotFound();     // 404
$this->assertRedirect($url);

Once you get in the habit of writing these tests, you’ll start automatically writing them when adding new routes, making it harder to forget authorisation. You’ll also find you consider authorisation and permissions more, potentially avoiding assigning the wrong permissions or leaving access too open on sensitive routes.

Authorisation Resources

To learn more about Authorisation in Laravel, you can find all of the past Tips at: https://securinglaravel.com/t/authorization.

In Depth: Policy Objects

In Depth: Policy Objects

Stephen Rees-Carter
·
April 26, 2022
Read full story
In Depth: Signed URLs

In Depth: Signed URLs

Stephen Rees-Carter
·
May 28, 2022
Read full story
In Depth: Insecure Direct Object References (IDOR)

In Depth: Insecure Direct Object References (IDOR)

Stephen Rees-Carter
·
August 1, 2022
Read full story
Security Tip: Policy Filters

Security Tip: Policy Filters

Stephen Rees-Carter
·
September 21, 2021
Read full story
1

This is why I always recommend doing authentication and authorisation within your routes file. You’re far more likely to notice missing auth* when you’re looking at all of your routes in a single place than you are when you’re looking at your controller logic across multiple methods and files.

2

Always ensure you’ve created all of the models you need for a successful request, otherwise a 404 due to route model binding may provide a false negative in your lacking authorisation tests.

3

The full list can be found at: https://laravel.com/docs/10.x/http-tests#available-assertions

4
Share this post

Security Tip: Test for Missing Authorisation

securinglaravel.com
5
Share
Previous
Next
5 Comments
Share this discussion

Security Tip: Test for Missing Authorisation

securinglaravel.com
Alex Millar
Jun 12Liked by Stephen Rees-Carter

Nice! After reading this got me thinking "how could I write an architecture test?" via pest to check for this and fail our CI/CD if you forgot the authZ

Expand full comment
Reply
Share
4 replies by Stephen Rees-Carter and others
4 more comments...
Top
New
Community

No posts

Ready for more?

© 2023 Stephen Rees-Carter
Privacy ∙ Terms ∙ Collection notice
Start WritingGet the app
Substack is the home for great writing