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

tnort's avatar
Level 4

Laravel app hacked

Hi,

I have a little Laravel app I am using as an internal tool, I noticed one of the blog titles was updated some time ago but I only noticed it now. The only user groups allowed to update stuff are super-admins. The controller is behind an isAdmin middleware.

I am sure I haven't breached any of the basic security measures such as:

do not allow root login in, use keys to ssh into the server, file permission is set to 755, the .env file is not reachable, the app is set to production and debug to false

I inspected the logs and it seems as if they tried somehow to edit one of the blogs but have failed a few times:

[2023-12-07 04:04:29] production.ERROR: in_array(): Argument #2 ($haystack) must be of type array, int given (View: /var/www/html/resources/views/admins/resources/posts/partials/post-form.blade.php) {"view":{"view":"/var/www/html/resources/views/admins/resources/posts/partials/post-form.blade.php","data":{"errors":"<pre class=sf-dump id=sf-dump-497589015 data-indent-pad=\"  \"><span class=sf-dump-note>Illuminate\Support\ViewErrorBag</span> {<a class=sf-dump-ref>#1920</a><samp data-depth=1 class=sf-dump-expanded>
  #<span class=sf-dump-protected title=\"Protected property\">bags</span>: <span class=sf-dump-note>array:1</span> [<samp data-depth=2 class=sf-dump-compact>
    \"<span class=sf-dump-key>default</span>\" => <span class=sf-dump-note title=\"Illuminate\Support\MessageBag
\"><span class=\"sf-dump-ellipsis sf-dump-ellipsis-note\">Illuminate\Support</span><span class=\"sf-dump-ellipsis sf-dump-ellipsis-note\">\</span>MessageBag</span> {<a class=sf-dump-ref>#1921</a><samp data-depth=3 class=sf-dump-compact>
      #<span class=sf-dump-protected title=\"Protected property\">messages</span>: <span class=sf-dump-note>array:1</span> [ &#8230;1]
      #<span class=sf-dump-protected title=\"Protected property\">format</span>: \"<span class=sf-dump-str title=\"8 characters\">:message</span>\"
    </samp>}
  </samp>]
</samp>}
</pre><script>Sfdump(\"sf-dump-497589015\", {\"maxDepth\":3,\"maxStringLength\":160})</script>


#<span class=sf-dump-protected title=\"Protected property\">with</span>: []
  #<span class=sf-dump-protected title=\"Protected property\">withCount</span>: []
  +<span class=sf-dump-public title=\"Public property\">preventsLazyLoading</span>: <span class=sf-dump-const>false</span>
  #<span class=sf-dump-protected title=\"Protected property\">perPage</span>: <span class=sf-dump-num>15</span>
  +<span class=sf-dump-public title=\"Public property\">exists</span>: <span class=sf-dump-const>true</span>
  +<span class=sf-dump-public title=\"Public property\">wasRecentlyCreated</span>: <span class=sf-dump-const>false</span>
  #<span class=sf-dump-protected title=\"Protected property\">escapeWhenCastingToString</span>: <span class=sf-dump-const>false</span>
  #<span class=sf-dump-protected title=\"Protected property\">attributes</span>: <span class=sf-dump-note>array:11</span> [<samp data-depth=2 class=sf-dump-compact>
    \"<span class=sf-dump-key>id</span>\" => <span class=sf-dump-num>993</span>
    \"<span class=sf-dump-key>author_id</span>\" => <span class=sf-dump-num>2581</span>
    \"<span class=sf-dump-key>title</span>\" => \"<span class=sf-dump-str title=\"30 characters\">Hacked By Oanda</span>\"
    \"<span class=sf-dump-key>slug</span>\" => \"<span class=sf-dump-str title=\"54 characters\">more-about-the-general-process</span>\"
    \"<span class=sf-dump-key>excerpt</span>\" => \"<span class=sf-dump-str title=\"61 characters\">&lt;p&gt;More About Us&lt;/p&gt;</span>\"

I looked at the code that updates a post which updates it based on its slug:

    public function update(PostManagementRequest $request,Post $post) {
		        $validated = $request->validated();
				$post->update($validated);
	}

the $validated data comes as part of a Request being validated

in the request class, I am checking for

public function authorize()
{
        return auth()->check();
}

So I assume the only way for someone to get here is if they are auth is that right? So following this idea then it looks like they hacked the account with ID 2581 thus getting in.

The above logs look like a Laravel debugger dump, but I am sure the debugger is off now, could be that I left it on when testing something?

0 likes
2 replies
martinbean's avatar

@tudosm I’d be extremely concerned that someone is able to either dump or dd variables on your page. This suggests to me you have some code somewhere that executes arbitrary PHP code as part of a POST request. If this is the case, then it would be easy to say, execute auth()->loginUsingId(1) or whatever to authenticate.

tnort's avatar
Level 4

@martinbean, thank you for the suggestion. I don't see any place it could happen as all user inputs are validated before being worked on. Any chance you could suggest a tool or something I can audit my app?

Please or to participate in this conversation.