Security Tip: Don't Use phpinfo()!

[Tip #112] It may seem like a harmless debugging tool, with a bunch of boring config values and version numbers, but phpinfo() is a goldmine of sensitive data - even when it's "protected" in an admin account! 😈

Security Tip: Don't Use phpinfo()!

I came across an interesting route during an audit a couple of months ago, and I was convinced I'd written about it already, but surprisingly I couldn't find an article anywhere on securinglaravel.com, so here it is...

This is the route I came across:

Route::get('phpinfo', function () {
    if (auth()->user()->is_admin) {
        phpinfo();
    } else {
        return redirect('home');
    }
});

At first glance, it looks like a pretty standard route with proper authorisation:

If the user is an admin, render phpinfo(), otherwise redirect to home.

This condition prevents anyone who isn't an admin from accessing phpinfo(), but my question is:

Why does the admin need access to phpinfo()?

The usual answer is for debugging, but it massively overshares everything for the potential of exposing a few single values for debugging purposes. Way more than you need for debugging issues, and it also overshares a lot of sensitive information.

Let's take a look:

phpinfo() output - system version numbers

We start out with some system version numbers - there are a lot in phpinfo(), basically every service/process that PHP can talk to - but for the sake of brevity, I'll just give you the above. Use your imagination for the rest.

As a hacker, version numbers are great! They let you look up known vulnerabilities, which you can immediately exploit without needing to explore 100s of possible attacks. 😱

phpinfo() output - environment variables

What's this? Environment variables... That's worrying...

phpinfo() output - environment variables

Oh... s***t. That's the applications APP_KEY! 🤬

That's really bad! If anyone gets access to this, they can decrypt encrypted values like cookies, and do things they really shouldn't! 😱

All the other API keys and credentials from your .env will be here too, exposing them as well. Needless to say, you've got big problems from this point forward.

phpinfo output - cookie values

Yep, that's your cookie! You know, the one protected by HttpOnly, which can't be accessed by Javascript, so can't be stolen by XSS... in plain-text on a webpage where XSS can now steal it.

This is so very bad. 😱😱😱

This makes it incredibly trivial for an attacker to hijack admin accounts. All they need to do is grab the admin's cookie from phpinfo() using XSS, throw it in their own browser, and they'll hijack the admin's account. 😈

Even when phpinfo() is only accessible to admins, if an attacker can get XSS to trigger in an admin account, they've got everything they need to completely compromise your app!

At this point hopefully you're already using the Global Find in your IDE to look for phpinfo(), and if you aren't, what are you waiting for??

🤦
Just before publishing this, I realised where I'd written about phpinfo() before - it's in part 2 of my Pentesting Laravel series, In Depth: Pentesting Laravel part 2 - Configs, Dependencies, and Routes.

As a side note, that's still my favourite series on Securing Laravel, so go check it out if you haven't already.

If you found this security tip useful, subscribe to get weekly Security Tips straight to your inbox. Upgrade to a premium subscription for exclusive monthly In Depth articles, or drop a coin in the tip jar to show your support.

When was the last time you had a penetration test? Book a Laravel Security Audit and Penetration Test, or a budget-friendly Security Review!

You can also connect with me on Bluesky, or other socials, and check out Practical Laravel Security, my interactive course designed to boost your Laravel security skills.