我有这个非常简单的脚本,允许用户指定任何网站的网址。该脚本替换对象标记上“data”属性的url,以在HTML页面上的对象内显示用户选择的站点。
我如何验证输入,以便用户无法从我的网站中加载任何页面,因为我注意到它会显示我的代码。
代码:
<?php
$url = 'http://www.google.com';
if (array_key_exists('_check', $_POST)) {
$url = $_POST['url'];
}
//gets the title from the selected page
$file = @ fopen(($url),"r") or die ("Can't read input stream");
$text = fread($file,16384);
if (preg_match('/<title>(.*?)<\/title>/is',$text,$found)) {
$title = $found[1];
} else {
$title = "Untitled Document";
}
?>
编辑:(更多详情) 这并不意味着代理。我让用户决定将哪个网站加载到对象标签(类似于iframe)。 php将要读取的唯一内容是输入URL中的标题标记,因此可以将其加载到我的网站标题中。 (不要担心它不会欺骗用户)虽然它可能会显示任何网站的标题,但它不会以任何其他方式绕过任何过滤器。
我也意识到我正在做的事情所涉及的漏洞,这就是为什么我要进行验证。
答案 0 :(得分:3)
正如gahooa所说,我认为你需要非常小心你在这里所做的事情,因为你正在玩火。可以安全地进行,但要对用户提供的URL中的数据做些非常谨慎。
对于您遇到的具体问题,我假设如果您输入了文件名,那么例如,如果有人在框中键入“index.php”。您需要做的就是确保他们的URL以“http://”开头,以便fopen使用网络方法,而不是打开本地文件。在fopen行之前的这样的事情应该可以解决这个问题:
if (!preg_match('/^http:\/\//', $url))
$url = 'http://'.$url;
答案 1 :(得分:3)
parse_url:http://us3.php.net/parse_url
您可以检查方案和主持人。
如果scheme是http,那么请确保主机不是您的网站。我建议使用preg_match来抓住点之间的部分。与在www.google.com或google.com中一样,使用preg_match来获取谷歌这个词。
如果主机是ip,我不确定在那种情况下你想做什么。默认情况下,preg匹配只会获得中间的2个数字和点(假设您尝试使用preg_match来获取.com之前的网站名称)
答案 2 :(得分:2)
您是否意识到您正在创建一个开放的HTTP代理,这可能是一个非常糟糕的主意?
你甚至需要获取URL的内容吗?为什么不让用户的浏览器通过提供URL来实现这一点?
假设您确实需要提取网址,请考虑针对已知的“白名单”网址进行验证。如果您不能将其限制为已知列表,那么您将再次返回到开放代理...
使用正则表达式(preg)确保它是一个好的HTTP URL,然后使用CURL扩展来执行实际请求。
将fopen()系列函数与用户提供的参数混合是潜在灾难的一种方法。
答案 3 :(得分:0)
您可以使用PHP过滤器。
filter_var($ url,FILTER_VALIDATE_URL)或 filter_input(INPUT_POST,'url',FILTER_VALIDATE_URL);
http://php.net/manual/en/function.filter-input.php
另外,请尝试与此过滤器相关的此PHP wiki帖子引用的这些文档 https://wiki.php.net/rfc/add_validate_functions_to_filter?s[]=filter 通过 Yasuo Ohgaki