我想由给定URL的用户使用file_get_contents()
阅读网页(不安全!)。我想禁止读取本地资源(文件,网页等)。如何通过file_get_contents()
拒绝访问本地服务器?
我尝试了以下代码,但显然还不够(许多名称可以映射到IPv4和IPv6环回)。
// URL from some web form; unsafe because user filled
$url = 'http://localhostXYZ/';
if (filter_var($url, FILTER_VALIDATE_URL) === false || preg_match('%^https?://%im', $url) === 0)
throw new Exception('Invalid URL.');
// do not allow localhost URLs (not complete!)
$components = parse_url($url);
if (empty($components['host']))
throw new Exception('No relative URLs allowed.');
if (strcasecmp($components['host'], 'localhost') === 0 ||
strcasecmp($components['host'], '127.0.0.1' ) === 0 ||
strcasecmp($components['host'], '[::1]' ) === 0)
throw new Exception('Localhost URLs allowed.');
// create a stream
$opts = array(
'http' => array(
'method' => "GET",
'header' =>
"User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0\r\n" .
"Accept: text/html\r\n" .
"Accept-language: de,en-US;q=0.7,en;q=0.3\r\n" .
"Referer: https://test.test/\r\n"
)
);
// open URL
$context = stream_context_create($opts);
set_error_handler(function () {
throw new Exception('Cannot read URL.');
}, E_WARNING);
// open the file using the HTTP headers set above
$file = file_get_contents($url, false, $context, 0, self::MaxContentLength);
restore_error_handler();
if ($file === false)
throw new Exception('Cannot read URL.');