针对 url 的单个输入的 PHP 输入验证

发布于 2024-07-14 19:01:40 字数 804 浏览 5 评论 0原文

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

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

I have this very simple script that allows the user to specify the url of any site. The the script replaces the url of the "data" attribute on an object tag to display the site of the users choice inside the object on the HTML page.

How could I validate the input so the user can't load any page from my site inside the object because I have noticed that it will display my code.

The code:

 <?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";
 }
 ?>

Edit: (more details)
This is NOT meant to be a proxy. I am letting the users decide which website is loaded into an object tag (similar to iframe). The only thing php is going to read is the title tag from the input url so it can be loaded into the title of my site. (Don't worry its not to trick the user) Although it may display the title of any site, it will not bypass any filters in any other way.

I am also aware of vulnerabilities involved with what I am doing that's why im looking into validation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

街角迷惘 2024-07-21 19:01:40

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

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

if (!preg_match('/^http:\/\//', $url))
    $url = 'http://'.$url;

As gahooa said, I think you need to be very careful with what you're doing here, because you're playing with fire. It's possible to do safely, but be very cautious with what you do with the data from the URL the user gives you.

For the specific problem you're having though, I assume it happens if you get an input of a filename, so for example if someone types "index.php" into the box. All you need to do is make sure that their URL starts with "http://" so that fopen uses the network method, instead of opening a local file. Something like this before the fopen line should do the trick:

if (!preg_match('/^http:\/\//', $url))
    $url = 'http://'.$url;
蓝色星空 2024-07-21 19:01:40

parse_url: https://www.php.net/parse_url

您可以检查方案和主机。

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

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

parse_url: https://www.php.net/parse_url

You can check for scheme and host.

If scheme is http, then make sure host is not your website. I would suggest using preg_match, to grab the part between dots. As in www.google.com or google.com, use preg_match to get the word google.

If the host is an ip, I am not sure what you want to do in that situation. By default, the preg match would only get the middle 2 numbers and the dot(assuming u try to use preg_match to get the sitename before the .com)

情深已缘浅 2024-07-21 19:01:40

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

您是否需要获取 URL 的内容? 为什么不让用户的浏览器通过提供 URL 来实现这一点呢?

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

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

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

Are you aware that you are creating an open HTTP proxy, which can be a really bad idea?

Do you even need to fetch the contents of the URL? Why don't you let your user's browser do that by supplying it with the URL?

Assuming you do need to fetch the URL, consider validating against a known "whitelist" of URLs. If you can't restrict it to a known list, then you are back to the open proxy again...

Use a regular expression (preg) to ensure it is a good HTTP url, and then use the CURL extension to do the actual request.

Mixing the fopen() family of functions with user supplied parameters is a recipe for potential disaster.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文