$ _SERVER ['REQUEST_URI']和标题('location:...')的任何安全问题;

时间:2013-03-05 02:21:03

标签: php security

我的网站有页眉,页脚和主要内容。如果用户未登录,则可以显示登录表单而不是实际内容。

在该登录表单上,我在会话变量$_SERVER['REQUEST_URI']中写了$_SESSION['redirect']

我的登录表单posthandler将登录用户,在通过header('location: http://myserver.com'.$_SESSION['redirect']);

成功登录此链接后将发送给用户

因此,如果我转到myserver.com/somesite.php?somevar=10,如果您已登录,则会显示正确的网站。否则会显示登录表单,但浏览器地址栏中的网址仍显示myserver.com/somesite.php?somevar=10 然后输入您的凭据,然后您将被重定向到myserver.com/somesite.php?somevar=10,这将是 - 因为您现在已登录 - 完全显示。

我不会将REQUEST_URI值用于表单操作或链接href。

此外,我使用的任何$_GET变量我首先检查它们是否与正则表达式匹配(通常变量将是sha1字符串或者只是随机生成的数字和字母字符串,没有特殊如果在db查询中使用get变量,我总是使用预准备语句。

我的问题是是否存在任何安全问题?有任何方法可以利用它,在网址中输入恶意内容,然后将其发送给其他用户,例如......?我是否应该在某个过程中以某种方式逃避某些事情?

4 个答案:

答案 0 :(得分:3)

关键规则是你总是检查你的输入/输出,看看你能控制什么,不能控制什么(因此,用户可以控制什么)。在此基础上,您应用安全/消毒措施。

如果我正确理解您的场景,则显示该页面,除非用户未登录。在这种情况下,您将显示一个登录框,并在成功登录后将用户发送回他尝试访问的页面$_SERVER['request_uri'](存储在会话中)。

因此用户显然可以控制此变量,他可以使用一些尴尬的字符浏览到您的页面。因此,你需要消毒它。正如@Wayne在评论中提到的那样,用户可以遍历您的目录树。

因此,与您的$_GET变量一样,您也需要清理$_SERVER['request_uri']。 有很多方法可以做到这一点。在使用request_uri或其他类似内容进行消毒后,最安全的可能是检查html_entities()是否是现有页面。请注意,..///./等特殊目录遍历方法可能会忽略传统的清理方法,例如前面提到的html_entities()

并按字面回答:我是否应该在某个过程中以某种方式逃避某些事情? - 是的,一切都在每个过程的开始。

------编辑@ 12-12-2013 -----

(评论的答案太长了,所以我将在这里说明用户可能使用目录遍历的方式,包括潜在的危险情况)

来自PHP手册:

$_SERVER['REQUEST_URI']: The URI which was given in order to access this page;
                         for instance, '/index.html'.

所以,说我想转到yourdomain.com/posts/post.php?../../../ssh你的webapp会注意到我没有登录,将post.php?../../../ssh存储在会话中并处理登录,之后它会将我发回给网址。由于../../../ssh部分,我不会发送到post.php,而是发送到您的webroot下面名为ssh的服务器上的目录。为方便起见,您已将SSH密钥存储在那里。这似乎是安全的,因为它不属于webroot,没有webuser应该能够访问它。 然而,我可以因为我的巧妙添加你的网址。

虽然这有点牵强,但正确配置的http服务器,chrooting环境等会阻止这种情况,这个例子确实告诉你,如果允许添加这些字符,它们可能会让用户访问它们所在的位置不应该。

根据您的实现,盲目地添加$_SERVER['request_uri']也可能意味着不需要的东西被添加到会话中,如果您将该会话存储在数据库中,它也将被添加到数据库中。我不是最新的安全PHP的最新版本,但我可以想象这可以打破会话变量并可能将内容注入数据库。

虽然不是所有事情都有可能,并且这个例子可能不太可能,但是防止这种行为更好而且并不难。

- 思想很小:也许header('location'...的东西是不安全的,但是这个:Is this PHP redirect insecure?显示它不是真的。然而,就像那里的评论者说:输入urlencode()

并不困难

答案 1 :(得分:1)

将ANYTHING置于网上有很多安全问题。在发布/获取请求中具有可识别的模式是一个问题,但它取决于很多因素,主要是......用户可以从弄乱您的网站获得什么,以及您对网站用户的恶意意图有多大的责任。 / p>

您应该对清理输入进行一些研究,使用会话令牌是您可以做的第一件事,以确保您的登录脚本的流量实际上是由您网站上的用户生成的。这两个常见的做法是保护agains sql注入和跨站点脚本攻击的第一步。 通过良好的数据库设计和良好的代码设计,确保您的数据受到保护的正确步骤。

我最喜欢的技术之一是将我的应用程序配置为使用自定义http标头,以及从Super Global检查接收数据的任何脚本,以确保在我的安全组件上正确提供自定义标头。任何黑客都可以轻松查看和嗅探这些标题,但是许多恶意攻击首先由脚本执行,而且只需要一步就可以轻松部署,这使您成为这类攻击的难点目标。 / p>

强化基于php的网站的快速谷歌搜索发现了这篇文章,其中有一些很好的提示:http://www.noupe.com/php/php-security-tips.html

答案 2 :(得分:1)

你永远不会100%安全。你可以看一下OWASP Top Ten。这些是主要的安全问题。

我认为你应该在$ _SESSION中有一个与每个用户关联的令牌(随机数),而不是$_SERVER['REQUEST_URI']。您可以通过POST(在隐藏的输入中)通过GET和令牌传递REQUEST_URI,然后验证它。如果此URI需要用户登录,请确保收到的用户令牌等于会话用户令牌。

答案 3 :(得分:0)

您正在重定向到相对URL,这很好,因为这意味着攻击者无法使用方法such as this使用session fixation来修改会话变量,并重定向到他们自己的域。您不应对此值进行任何编码,因为它是原始URI的直接副本,它也是您希望将用户重定向到的确切URI。您应该检查您使用的PHP版本是否不容易受到header injection的攻击。它似乎是fixed in PHP

  

4.4.2和5.1.2此函数现在可以防止一次发送多个标头,以防止标头注入攻击。

关于path traversal的其他答案不应该是一个问题,因为没有额外的风险比用户直接在他们的地址栏中键入路径。使用location标头重定向它们的事实不会增加此风险。但是,您应确保您的服务器平台不易受攻击,但请记住,这与您的重定向方法无关,因为location只是告诉客户端加载另一个地址。

请务必在setting your header之后致电exit,否则攻击者可以通过查看原始HTTP响应来查看您的网页内容: -

<html>
<?php
/* This will give an error. Note the output
 * above, which is before the header() call */
header('Location: http://www.example.com/');
exit;
?>

我无法评论您的网站可能存在的每个漏洞,但实质上您建议进行重定向的方式应该是安全的。但是,您应确保仅通过HTTPS访问您的站点,这将加密连接并确保其免受MITM攻击。您还应该在会话cookie上设置secure flag,以确保它不会通过非HTTPS连接泄露。