Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

pmattheew's avatar

Authentication breach in Laravel 6

Hey guys

I've been working with a legacy Laravel 6 codebase (a lot of spaghetti code), and we're having a problem where somebody is inserting a lot of trash, random users in our database sporadically

It has a pattern, like everyday at least one trash user is inserted, and there are somedays that 2 or more are inserted.

So I started investigating and I see that probably it is being done through the actual API endpoint for creating users (POST /admin/users/create), but it is protected by an 'auth' middleware, so it should be protected - I've already tried doing requests into it using Postman but it gives the 419 error because of the XRSF token (I tried adding this cookie forcefully in Postman but it gave the same error).

I believe that the problem is in this endpoint, because I've created a UserObserver to log suspicious users being created, and it is catching correctly the moment that these trash users are being created.

Let's look at it: UserObserver.php

<?php

namespace App\Observers;

use App\User;
use Illuminate\Support\Str;

class UserObserver
{
    public function created(User $user)
    {
        if (Str::endsWith($user->email, ['@gmail.com', '@yahoo.com'])) {
            $creator = auth()->user();

            \Log::channel('monitored_users')->info('User created using a suspicious email address', [
                'user_id'    => $user->id,
                'email'      => $user->email,
                'ip_address' => request()->ip(),
                'user_agent' => request()->userAgent(),
                'creator_id'   => $creator ? $creator->id : null,
                'creator_email'=> $creator ? $creator->email : null,
            ]);
        }
    }
}

I configured it to display the user that is creating this suspicious user. It works when I do it by myself, logging like this:

[2025-04-01 21:43:47] dev.INFO: User created using a suspicious email address {"user_id":3,"email":"[email protected]","ip_address":"172.18.0.1","user_agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36","creator_id":2,"creator_email":"[email protected]"}

But when the intruder insert, it doesn't display its logged in user:

[2025-04-01 08:31:58] production.INFO: User created using a suspicious email address {"user_id":515,"email":"[email protected]","ip_address":"111.90.176.158","user_agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36","creator_id":null,"creator_email":null} 

I'm going to implement a middleware now that asks if the user is an admin of the system (yes, this check didn't exist in this API before - but existed in the interface, client code), but I'm a bit worried if it would have any other possible side effect.

Here goes a piece of my web.php:

<?php

Route::get('/', 'FrontEndController@index');

Auth::routes();


Route::permanentRedirect('/public', '/admin');


/* ADMIN */
Route::group(["prefix" => "admin", 'middleware' => ['auth']], function () {

	// a bunch of other route groups

	Route::group(['prefix' => 'users'], function () {
		Route::get('', ['as' => 'auth', 'uses' => 'LoginController@index']);
		Route::post('create', ['as' => 'users.create', 'uses' => 'LoginController@create']);
		Route::post('edit', ['as' => 'users.edit', 'uses' => 'LoginController@edit']);
		Route::get('{id}/edit', ['as' => 'users.edit', 'uses' => 'LoginController@edit']);
		Route::put('{id}/update', ['as' => 'users.update', 'uses' => 'LoginController@update']);
		Route::get('{id}/destroy', ['as' => 'users.destroy', 'uses' => 'LoginController@destroy']);
	});

	// a bunch of other route groups

   // basically the whole system is inside this admin group =)
});

So after all of this, I configured the logger to not log only that things but log the whole request.

Maybe with only this information I gave it isn't possible to have conclusive assertions of what is happening, and considering that I might solve it with the 'admin' middleware wouldn't encourage you to answer me

But I'd really like some guidance in securing an Laravel application, so I would be able to check at my side what lead to this exposure, as I've already found other security breaches in this application (e.g., their Redis database was exposed to the internet, with this intruder changing it to read-only mode sporadically and breaking the system)

Thanks for your time =)

2 likes
4 replies
martinbean's avatar
Level 80

@pmattheew I’d instead be checking the server logs for the corresponding POST requests for the created users, which will also show which endpoint is being used to create the users in the first place.

So for example, if a “trash” user is created with the email address [email protected] then look in your raw server logs for the request with that email address in the request body, and you’ll be able to see what URI the request was sent to (and therefore the controller handling that request), and that’s where your vulnerability is.

1 like
pmattheew's avatar

@martinbean thank you so much!

I looked at my apache logs and there it was!

it was requests being done into /register route actually, and not this one that I thought first

I mainly thought that it was happening to /admin/users/create because it is the only route used to create users today in the system

my web.php even gives a small hint of what should be happening, once there was the Auth::routes() and later the create route inside /admin/users/

this /register route was being defined by the Auth::routes()

reading the docs I found that there is a option to remove it, simply doing this:

Auth::routes(['register' => false]);

My logger couldn't help that much, I could use it just to find the line that it happened through the IP address in apache's log file =o

It was a big mistake by the devs that were working in the project before, and today I have nothing else to do but put out the fire LOL

1 like
martinbean's avatar

@pmattheew Glad you found the problem and sorted it. Now get that application upgraded from version 6 😉

1 like

Please or to participate in this conversation.