0

我有这个非常简单的脚本,它允许用户指定任何站点的 url。该脚本替换对象标记上的“数据”属性的 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 中的标题标签,因此可以将其加载到我网站的标题中。(不要担心它不会欺骗用户)虽然它可以显示任何网站的标题,但它不会以任何其他方式绕过任何过滤器。

我也知道我正在做的事情涉及的漏洞,这就是我研究验证的原因。

4

4 回答 4

3

正如 gahooa 所说,我认为你在这里所做的事情需要非常小心,因为你在玩火。可以安全地进行操作,但要非常谨慎地处理用户提供给您的 URL 中的数据。

对于您遇到的特定问题,我假设如果您输入文件名,例如如果有人在框中键入“index.php”,就会发生这种情况。您需要做的就是确保它们的 URL 以“http://”开头,以便 fopen 使用网络方法,而不是打开本地文件。在 fopen 行之前这样的事情应该可以解决问题:

if (!preg_match('/^http:\/\//', $url))
    $url = 'http://'.$url;
于 2009-02-23T07:53:45.977 回答
3

parse_url:http ://us3.php.net/parse_url

您可以检查方案和主机。

如果方案是 http,则确保主机不是您的网站。我建议使用 preg_match 来抓取点之间的部分。就像在 www.google.com 或 google.com 中一样,使用 preg_match 来获取 google 一词。

如果主机是 ip,我不确定在这种情况下你想做什么。默认情况下,preg 匹配只会得到中间的 2 个数字和点(假设你尝试使用 preg_match 来获取 .com 之前的站点名称)

于 2009-02-23T09:02:55.670 回答
2

您是否知道您正在创建一个开放的 HTTP 代理,这可能是一个非常糟糕的主意?

你甚至需要获取 URL 的内容吗?为什么不让用户的浏览器通过提供 URL 来做到这一点呢?

假设您确实需要获取 URL,请考虑针对已知的 URL“白名单”进行验证。如果您无法将其限制为已知列表,那么您将再次回到开放代理...

使用正则表达式 (preg) 确保它是一个好的 HTTP url,然后使用 CURL 扩展来执行实际请求。

将 fopen() 系列函数与用户提供的参数混合使用会导致潜在的灾难。

于 2009-02-23T07:22:26.613 回答
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 帖子引用的这些文档,这些文档与 Yasuo Ohgaki 的过滤器https://wiki.php.net/rfc/add_validate_functions_to_filter?s[]=filter相关

于 2017-05-24T21:54:36.477 回答