The fix, in one snippet
find /var/www -name 'phpinfo.php' -o -name 'info.php' -delete
Illustrative values. Change the paths, hostnames and options to match your own site before using it.
The sections below explain what is tested, why it matters and the alternatives.
What we test
Scan.now requests /phpinfo.php, /info.php, /php.php and /test.php, in that order, stopping at the first hit. A finding requires an HTTP 200 whose body contains the distinctive markers of the phpinfo() output: a <title>PHP Version or phpinfo() title, the "PHP License" footer, and the configuration table structure. Generic pages that happen to live at those paths do not match. The report records the path and the PHP version shown; it does not retain the rest of the page. Rated high because of how much the page reveals in one request. Related: x-powered-by-disclosure for the version leak in headers, and exposed-env-file for the same secrets in file form.
Why it matters
phpinfo() is a diagnostic dump that developers leave behind after setting up a server. It reveals the exact PHP version and build, every extension and its version (each a CVE lookup), php.ini settings such as disable_functions, open_basedir, allow_url_include and session.save_path, absolute filesystem paths, the document root, the server's internal IP addresses, and the full environment and $_SERVER arrays. On container and platform deployments where configuration is injected as environment variables, that last section prints database URLs, API keys and cloud credentials verbatim. Even without secrets, the page is a map: knowing session.save_path and upload settings is what turns a local-file-inclusion bug into remote code execution in the classic phpinfo race technique. The exposed files guide discusses debug pages in general.
How to fix it
Delete the file and search for any others:
grep -rl 'phpinfo()' /var/www --include='*.php'
Block the common names so a future test file is not served. nginx:
location ~* ^/(phpinfo|info|php|test)\.php$ {
return 404;
}
Apache:
<FilesMatch "^(phpinfo|info|php|test)\.php$">
Require all denied
</FilesMatch>
Disable the function in production so that even an injected call prints nothing, and stop advertising the version:
; php.ini
disable_functions = phpinfo
expose_php = Off
Symfony and similar frameworks sometimes ship a config.php or profiler page with the same content; do not deploy development-only entry points. If the page was exposed on a host that keeps secrets in environment variables, rotate them. Cloudflare's WAF managed rules block many well-known diagnostic paths, but the origin fix is what counts.
Where this fits
Exposed phpinfo() page is check 4 of 14 that the website vulnerability scanner runs under exposed files and information disclosure, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.
Fix this one first
Above it in the same category sits Exposed backup or archive files (high), where a backup archive, database dump or editor backup copy of a configuration file is downloadable from the web root, exposing source code, credentials and user data. An attacker who has that does not need this, so it is the better use of the same hour.
What fixing this still leaves open
Exposed phpinfo() page closes one route in. Immediately below it: Directory listing enabled, where the web server generates an index of files for a directory that has no index page, exposing every file in it, including ones that are not linked from anywhere; Exposed server status page, where a server status page (Apache mod_status, nginx stub_status or PHP-FPM status) is reachable from the internet, revealing live requests, client IPs, internal hostnames and load details; WordPress user enumeration via REST API, where the WordPress REST API or author archives reveal account usernames to anonymous visitors, giving attackers half of each credential pair before they start guessing passwords.
Found in the same scan
The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and HTTPS is available, where the site could not be reached over HTTPS on port 443, or the TLS handshake failed. A single run of website vulnerability scanner answers all of them at once.
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.
Finding: Exposed phpinfo() page (high severity)
Scanner check id: exposed-phpinfo
The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.
Sign in with GoogleSigning in is free and takes one click. We store your email address and nothing else.