Table of contents of the article:
Anyone who deals with systems and security knows it: a page phpinfo() Forgotten on a production server is one of the most welcome gifts we can give an attacker. It's pure information, served on a silver platter, that tells us practically everything about our infrastructure. In this article, we want to turn the tables: instead of simply hiding it, what if we used it as a esca? That's exactly the idea behind it. FakePHPInfo, a small PHP wrapper we developed and want to share with you.
It can be downloaded on GitHub and is composed of a single phpinfo.php file. https://github.com/MarcoMarcoaldi/fakephpinfo
Why phpinfo() is a goldmine for attackers
When an attacker performs the phase of recognition against a target, a page phpinfo() Being publicly accessible provides them with information of enormous value. Among the most critical:
- The real IP address of the server (the variable
SERVER_ADDR). This is especially valuable when the site is protected by a CDN or WAF like Cloudflare: knowing the originating IP allows you to completely bypass the protection and attack the server directly. - The actual hostname of the machine, useful for lateral movement and DNS enumeration of the infrastructure.
- The absolute routes of the filesystem (
DOCUMENT_ROOT,include_path, log location), valuable for building targeted payloads and LFIs. - The complete list of uploaded extensions and configuration directives, from which to deduce vulnerable versions and enabled dangerous functions.
The golden rule, obviously, remains one: never expose phpinfo() in productionBut what if instead of simply removing it, we could turn the gun against those who attack us?
The idea: deception instead of simple removal
The concept of deception (deception) is one of the pillars of modern active defense. Instead of simply closing a door, we build a fake, plausible, and guarded room behind it. An attacker who finds a page phpinfo() Apparently real, it will consider it authentic and act accordingly: it will save the IP, use it for its bypass attempts, feed it to its automatic tools.
And if that IP and hostname point to a honeypotAt that point we would have achieved four results in one fell swoop:
- To deviate the attacker away from the real infrastructure.
- Attract him inside a monitored decoy system, where he can calmly study his techniques and tools.
- Make him waste time and resources against a dummy target.
- Gather threat intelligence: IP address, user agent, attack pattern.
How FakePHPInfo Works
The operation is elegant in its simplicity. The script generates a page phpinfo() identical to the original in every detail, with one difference: all occurrences of the real hostname and IP addresses are replaced with dummy values pointing to our honeypot. Everything else—PHP version, modules, paths, directives—remains completely authentic, so the page doesn't arouse the slightest suspicion.
The first step is to capture the actual output of phpinfo() using PHP's output buffering, so you can manipulate it before sending it to the browser:
ob_start(); phpinfo(); $output = ob_get_clean();
The script then automatically detects all the server's real identifying values, drawing from multiple sources to leave nothing to chance:
$real_hostname = gethostname();
$real_ip = $_SERVER['SERVER_ADDR'] ?? gethostbyname($real_hostname);
$real_ipv6 = '::ffff:' . $real_ip;
$real_server_name = $_SERVER['SERVER_NAME'] ?? $real_hostname;
$real_http_host = $_SERVER['HTTP_HOST'] ?? $real_hostname;
// Rimuove l'eventuale porta dall'HTTP_HOST prima della sostituzione
$real_http_host_no_port = preg_replace('/:\d+$/', '', $real_http_host);
At this point a substitution map is constructed in the form real value → fictitious valueThere's an important technical detail here: order matters. The longest and most specific strings should be replaced first. Think of the mapped IPv6 address. ::ffff:1.2.3.4: if we first replaced the simple 1.2.3.4, we would corrupt the IPv6 representation. Therefore, the script sorts the substitutions by decreasing length:
// Ordina le chiavi per lunghezza decrescente: prima le stringhe più lunghe
uksort($replacements, function ($a, $b) {
return strlen($b) - strlen($a);
});
$output = str_replace(
array_keys($replacements),
array_values($replacements),
$output
);
echo $output;
The modified page is then sent to the browser. For the attacker, this is a complete scam. phpinfo() real; in fact every reference to infrastructure has been hijacked.
What is replaced and what remains authentic
The philosophy is to touch the bare minimum to maintain maximum credibility. The following are replaced:
- The line "System" at the top of the page (the kernel hostname).
$_SERVER['SERVER_ADDR']— the server IP.$_SERVER['SERVER_NAME']— the name of the virtual host.$_SERVER['HTTP_HOST']— the value of the Host header.- Any other occurrences of the hostname or real IP in the rest of the output, including the FQDN hostname returned by
php_uname('n'), which may differ fromgethostname().
Instead, stay perfectly real everything else: PHP version and build, loaded extensions and their configuration, directives php.ini (local and master values), filesystem paths, environment variables, and request headers. It's precisely this underlying authenticity that makes the deception convincing.
Setup and installation
The configuration is reduced to a few lines at the top of the file. Just enter the values for your honeypot:
// === CONFIGURAZIONE: inserisci qui i valori fittizi (honeypot) === $fake_hostname = 'honeypot.example.com'; $fake_ip = '192.168.100.50'; $fake_ipv6 = '::ffff:192.168.100.50'; // Opzionale: porta fittizia (lascia null per mantenere quella reale) $fake_port = null;
A quick guide to the parameters:
- $fake_hostname: the hostname (FQDN) of your honeypot, which will replace the real one.
- $fake_ip: the IPv4 address of the honeypot.
- $fake_ipv6: the IPv6-mapped representation of the dummy IP, normally
::ffff:followed by$fake_ip. - $fake_port: an optional dummy door. It is recommended to leave it open.
null: Changing the visible port often risks appearing more suspicious than useful.
For deployment, simply upload the file to the web server with the name phpinfo.php (or any other name) in a location where an attacker is likely to snoop: the web root, or “tasty” paths like /info/ o /debug/.
An even more refined approach consists in serve the page conditionally: through .htaccess or the web server configuration can be made so that non-whitelisted IPs receive the dummy version, while your team — connected from authorized IPs — sees the dummy version when needed. phpinfo() real.
Security considerations
It is worth being honest about the limitations of the tool, because deception is a weapon that must be handled with awareness:
- FakePHPInfo is a deception aid and threat intelligence, not a substitute for hardening. The most effective measure of all remains not to expose at all.
phpinfo(). Use only as an intentional and monitored lure. - All non-identifying data (PHP version, extensions, paths, directives) remain Really and they are still disclosed. Make sure this is acceptable in your threat model.
- Substitution is a simple string operation: if your actual hostname is a very short or common substring, check the output to make sure no unrelated text fragments are accidentally altered.
Conclusions
FakePHPInfo was born from a principle that is close to our hearts: in security we must not only think about defense, but also about intelligent counterattackA page that's normally a vulnerability can, with just a few lines of code, become an information-gathering tool and a trap that wastes the time and resources of those trying to attack us. It's deception applied in the simplest and most cost-effective way possible.
The tool is released under the GNU GPL v2 (or later) license and is freely usable and modifiable. We encourage you to integrate it into your active defense strategy and, why not, contribute improvements. Because the best way to protect an infrastructure, sometimes, is to make the adversary believe they've already found it.