Current situation: PHP2Shell. Two critical PHP vulnerabilities (CVSS 9.2) allow malicious code without login. Patches since 21 October 2026.What to do now →

phpinfo() Files: Why They Must Disappear

After PHP2Shell, many admins quickly create an info.php. Why such files are a data leak, how to find them and which ways of checking are better.

Last updated 6 min readSecure development

In short: A file that merely calls phpinfo() shows every visitor the version, modules, paths and settings of PHP, often also environment variables with credentials. For phpinfo security, the following therefore applies: never leave such files permanently in the web root, delete them after use and rather check the PHP status through package management and configuration. A phpinfo output does not prove the patch level against PHP2Shell anyway.

The Test File That Stays

Since 21 October 2026, thousands of admins have been checking which PHP version their websites deliver. The quickest way is well known: create a file info.php with a single line, open it in the browser, read off the result. That works. The problem begins afterwards, when the file is forgotten.

Such files survive surprisingly long. They travel along in moves, end up in backups and turn up after years in directories nobody knows anymore. Automated scanners constantly query typical file names. What was a tool for the admin is a blueprint of the server for an attacker.

Agencies and hosts with many customer sites are particularly affected. Anyone who checks dozens of websites in a hectic week quickly creates dozens of test files. A single forgotten folder is enough for the file to still be retrievable months later.

What phpinfo() Reveals and Why It Matters for Security

According to the PHP manual, phpinfo() outputs the current state of PHP. Constants control which parts appear; without an argument, it is everything.

Area (constant) Content according to the manual Why delicate
INFO_GENERAL build, location of php.ini, web server, system reveals operating system and paths
INFO_CONFIGURATION local and master values of all directives shows whether disable_functions or open_basedir take effect
INFO_MODULES loaded extensions with settings attackers see which functions are available
INFO_ENVIRONMENT environment variables database or API credentials are often found here
INFO_VARIABLES predefined variables (environment, GET, POST, cookie, server) contains headers and cookies of the current request

The last two rows are the most dangerous. Modern applications like to load credentials from environment variables, for example from a .env file or from the container configuration. These values then appear in plain text in the output. How to protect such secrets in general is described in the article Protecting Credentials and .env Files Properly.

In addition: the output shows the values of the running request, that is, also cookies and headers. If an attacker can lure a visitor to the page and read the response, for example via a cross-site scripting vulnerability elsewhere, even cookies marked HttpOnly become visible.

Why phpinfo Is No Proof Against PHP2Shell

Many have just created the file to check the patch level. That is exactly what it is only conditionally suited for. Distributions and hosts often apply fixes as backports; according to reports, for example, Ubuntu 24.04 continues to show 8.3.6 after the update. The displayed number therefore says little. Conversely, a current number does not prove that all workers were restarted.

What holds up is the package state with the CVE numbers in the changelog, supplemented by the restart of all PHP processes. How to do this is explained in the article Checking PHP Version and Patch Level Correctly.

A brief output in the web context still has its place: it shows which php.ini and which values actually apply to the website, because the command line often reads a different configuration. Background on levels and precedence is explained in The php.ini Explained. If you need it, do it access-protected, with a random file name and only for minutes.

For most questions there are better ways anyway. The PHP version of an FPM pool is in its configuration and in the process list. Individual values can be queried with a script outside the web root via ini_get() without revealing everything. And in hosting panels, the interface shows the assigned version per website, though without any statement about backports.

Finding Forgotten Files: Concrete Check Steps

This is how you track down legacy files on a Linux server. The commands only read and change nothing.

  1. Search for files with a phpinfo call (adjust the path):
grep -rlE "phpinfo[[:space:]]*\(" /var/www --include="*.php" 2>/dev/null
  1. Check typical file names, even without a match in the content:
find /var/www -type f \( -iname "info.php" -o -iname "phpinfo.php" -o -iname "test.php" -o -iname "i.php" \) 2>/dev/null
  1. Evaluate matches: Not every match is a test file. Admin tools, panels or frameworks may use phpinfo() behind a login. What matters is whether the file is reachable from the internet without a login.

  2. Check accesses in the log before you delete:

grep -E "GET /(info|phpinfo|test|i)\.php" /var/log/nginx/access.log* 2>/dev/null | tail -n 50
  1. Delete and replace secrets: If a password or key appeared in the output and the file was public, the value counts as known. Change it.
Tip

A match with an unknown creation date and conspicuous content next to the phpinfo call may also be a backdoor. In that case, do not just delete it but secure it and have it examined, see Detecting and Removing Webshells.

Prevent It for Good Instead of Cleaning Up

Three measures make sure the topic does not come back. First: add phpinfo to the disable_functions list in the php.ini for the web context. First check whether your panel needs the function for a status page. How the setting works and where its limits lie is explained under Using disable_functions Correctly.

; php.ini for FPM or Apache, then restart all PHP processes
disable_functions = phpinfo
expose_php = Off

Second: deployment only through a fixed process, such as Git or a build pipeline, so that no individual files get into the web root by hand. Third: status information belongs in monitoring or inventory, not on a public page.

expose_php = Off additionally removes the header with which PHP announces its version in every response. That does not replace an update but takes a convenient piece of information away from automated scanners. If several people have server access, you should also agree on a simple rule: test files are deleted in the same working step in which they were created, and not "later".

How does PHP SOS help?

  • We search your web roots for phpinfo files, test scripts and other legacy files and assess every match.
  • We evaluate the accesses to files found and tell you which secrets you should replace.
  • We prove the patch level against PHP2Shell via package changelog and process restart rather than via a version display.
  • We implement disable_functions, expose_php and further hardening permanently as part of server hardening.

Conclusion: A phpinfo file is created in seconds and forgotten just as quickly. Anyone who looks for it and removes it now closes an unnecessary data leak and relies on solid evidence for the patch level.

Frequently asked questions

Is a phpinfo file a security vulnerability in itself?

It does not open up access, but it gives attackers a detailed description of the server: version, modules, paths, settings and, depending on the environment, environment variables. That facilitates targeted attacks and can expose credentials.

Does the version number in phpinfo prove that PHP2Shell is patched?

No. Distributions and hosts often apply fixes as backports, and the displayed number then stays the same. The patch level is proven by the package changelog and the provider's confirmation, plus the restart of all PHP processes.

What should I do if a phpinfo file was public for a longer time?

Delete the file, check the access log to see who retrieved it, and replace all secrets that appeared in the output, such as database passwords or API keys from environment variables.

Can I disable phpinfo() completely?

Yes, via disable_functions in the php.ini of the web context. First check whether a panel or an application uses the function for status pages, and restart the PHP processes afterwards.

Sources

Immediate contact

Every hour counts. Write to us now.

Briefly describe your system, PHP version and observation. We will get back to you, clarify the situation and work remotely until the incident is closed and documented.

Immediate help