在URL中发送参数的最佳和安全方式

时间:2014-03-18 05:01:18

标签: php security url zend-framework zend-framework2

我正在开发一个网站,其中有基于id更新和删除数据的功能。现在我担心的事情就像我的网址一样

  

www.example.com/public/controller/action/1

如果操作为delete,则任何人都可以在网址中change id from 1 to 2,并且ID为2的数据会被删除。什么是保持流量安全的最佳方法。我正在使用Zf2和Doctrine2 ......请提出任何建议!而且我保持id隐藏在字段中,任何人都可以使用firebug来改变字段中的值,有没有办法保护数据呢?

任何加密 - 解密方式是否会使其安全,就像任何人甚至编辑加密值一样,在解密后不会产生必需的ID?哪一个会好,我从未使用加密解密。

8 个答案:

答案 0 :(得分:9)

当人们更改URL中的参数或尝试破解HTML(隐藏字段)中的内容时,您应该更少担心会发生什么事情,因此您应该担心用户实际上可以做什么。

如果允许管理员删除所有帖子,那么将domain.com/post/delete/1更改为domain.com/post/delete/42并不重要。如果管理员应该删除他们可以做的一切。因此,让他们尽可能多地改变它。

如果管理员只允许获得自己条目的管理权限,那么您需要将其用于服务层。服务层将检查当前用户对当前请求的对象的权限。我个人最喜欢的是ZfcRbac

但是,如果您想让人们更难以实际更改ID,那么您应该为每个条目提供唯一的哈希值。例如,url将是domain.com/post/delete/12acd-4a7f7c6-4a7f7c6-12acd-4a7f7c6或类似的东西。

TL / DR 不要担心当人们更改网址/ HTML中的内容时会发生什么,只需担心身份验证和权限。

答案 1 :(得分:2)

您可以将id更改为some_random_string(基于时间戳使其唯一)并搜索数据库。 用户不可能猜到随机字符串。 第二次检查控制器,记录的用户有权使用CRUD操作。

你可以使用https://github.com/ZF-Commons/ZfcUser(第二个模块用于Doctrine) 要进行身份验证并在控制器中,您可以检查用户是否已登录

if ($this->zfcUserAuthentication()->hasIdentity()) {
    $user = $this->zfcUserAuthentication()->getIdentity();
    if($user->systemRole=='admin')//you can make switch for that
    {
      //can edit/delete/create
    }
}

要完成此工作,您必须从该模块复制UserEntity并添加systemRole。 (查看zfc-user的文档)

答案 2 :(得分:1)

1-尝试检查授权。
2-在某些情况下,您可以在页面加载时在会话中保存一些数据,例如实体ID,然后只调用delete 3-任何加密算法都有一个(或多个)密钥。安全管理的一些重要部分是密钥管理。如果您在PHP和Javascript中实现了算法,那么您应该在两侧都有密钥进行解密(用户可以在客户端代码中找到您的密钥)
4-哈希可以帮助你。 hash do,需要键入并使您的数据不可读但黑客可以使用哈希数据调用您的URL http://en.wikipedia.org/wiki/Cryptographic_hash_function

更新1:
对于加密,您可以将服务器和客户端上的可访问数据用作密钥。例如,使用“url character count”作为键
网址字数:10
id(普通数据):23
id(加密并用于发送到服务器)33 = 23 + 10
在服务器上你应该解密id(id = id - url字符数)

重要的一点: 加密算法应该在客户端上极度缩小和混淆。

答案 3 :(得分:0)

使用数据发送网址的最安全方式是使用ssl(https)进行安全连接。但是,我不认为这是你要问的问题。

我认为您希望阻止某些人或某些人(角色)访问某些资源。如果是这种情况,则需要访问控制列表,并且应使用\ Zend \ Permissions \ Acl组件。

编辑:

在PHP中加密数据的最佳方法是使用现代可逆加密函数,如mcrypt_encryptmcrypt_decrypt

然而,这只是模糊了网址,它并没有完全保护你免受某人只是让机器人检查所有可用的删除网址(给定,可能有很多)。

保护某些页面(资源)的唯一防弹方法是使用某种类型的访问控制。比如说,您只希望特定用户能够删除自己的帖子。你可以有一个动作deleteMyPost。 (我假设您有一个用户登录该网站以执行操作,否则,所有投注均已关闭)。当有人访问www.mysite.com/public/controller/deleteMyPost/1时,操作或ACL将检查id为1是否为登录用户的帖子。如果没有,用户将以某种方式重定向远离页面,可能会进行header('Location: <url>')调用。

答案 4 :(得分:0)

您所询问的内容与ZendFramework有perfectly working library的ACL有关。在ACL中,您将首先配置谁可以在哪个资源上执行操作,然后您将查询它以查看某个用户是否允许某些请求。以下是ACL的部分:

  • 用户
  • 动作
  • 资源

例如:

  • 用户:Mehran
  • 操作:删除
  • 资源:表T1的任何记录

但是在ZF行动和资源合并成一个没什么大不了的。在ZF中,您需要说Action_Resource。我要在这里展开的是你可能面临的资源类型。在我看来有两个:

  1. 静态资源。
  2. 动态资源。
  3. 静态资源是您在设计软件时可以(完全)列出的资源。例如您可能在软件中有帖子,您可能希望授予某些用户删除它们的权限。如果您不向其他用户授予此类许可,则他/她不能删除任何帖子。但如果你确实把它交给某人,那么他可以删除他想要的任何帖子(假设我们还没有包含动态资源)。换句话说,静态资源是动态资源类型

    此外,我们拥有在部署软件之前不存在的动态资源。事实上,动态资源是由最终用户创建的。所以他们有业主。您可能只想将动态资源的删除权限授予其所有者。扩展与以前相同的示例,任何特定的帖子都可以是动态资源。

    在我得出结论之前,我想扩展计算机世界中的行为类型(一般而言)。通常,您可以假设只有四种类型的操作:

    1. 创建
    2. 修改
    3. 删除
    4. 如果您想检查上述某个操作的权限,则只有创建处理静态资源,其余的则讨论动态资源。也就是说,当您创建帖子时,尚未创建动态资源,因此您所能做的就是坚持使用静态资源。但在所有其他动作类型中,总是有一个动态资源包含在您的权限检查中。

      现在把这两种资源放在一起,你就有了决定。如果动态资源可用,我应该检查具有动态资源或其静态资源的权限(因为所有动态资源将始终具有静态资源作为其类型)?这个问题的答案通常是:他们两个。方法如下:

      1. 用户可以删除:他有权访问静态动态资源。
      2. 用户可以删除:他有权访问静态动态资源。
      3. 在第一种情况下,任何用户都可以删除自己的资源,如果他被授予了权限。但没有人能够这样做。在第二种情况下,任何所有者都可以删除自己的资源,无论是否授予任何其他权限。但您也可以向不是所有者的某个管理员授予删除权限。通常情况下是后一种情况。

        说完这一切之后,在你的情况下,你正在谈论检查对某些动态资源的访问,你需要为它实现一个ACL。

答案 5 :(得分:0)

我提出了一种动态方法:

此方法的本质是基于识别单个用途。

1 - 您为每个标识符创建一个新的唯一标识符 例如,对于标识符$ id1,您可以执行以下操作:

$new_id1 = uniqid(sha1("$id1")). / / Just for example

然后将所有这些标识符放在一个数组中:

array ($new_id1 => $ id1,
       $new_id2 => $ id2,
       .....
       / / I advise you to have a trace logger for in case of problems.

2 - 如果已存在

,则在删除后将此数组放入会话(或缓存)中

3 - 您使用新标识符创建链接:

<A href = "/Controller/Action/". $new_id1 . "> link text </ a>

用户只能访问他的页面标识符(因此它拥有权限)并且很难(非常非常......非常难:) :)按下来查找另一个标识符。

4 - 当PHP检索标识符$ new_id1时,它将在会话(或缓存)中获取数组以获取真实标识符($ id1)。

5 - 从会话(或缓存)中删除数组以便无法使用(单次使用)

根据您的要求水平,可以增强此方法。

  • 您可以使用表单而不是链接。

    &LT; a onclick =&#34; submit_form(&#34;。$ new_id1。&#34;)&#34;&gt;您的文字链接&lt; / a&gt; ...     

submit_form()用好值填充隐藏元素 您可以添加Hash元素以防止CSRF攻击。

  • 如果标识符php端不在数组中,您可以断开此人并可能放入黑名单

  • 动态路由还有其他可能性。生成一个没有控制器和新ID的URL,如果识别出该id,则将其路由到正确的控制器。

祝你好运

答案 6 :(得分:0)

$token = sha1("id=1&action=delete");

$url = "www.mysite.com/public/controller/action/delete/id/1/token/".$token;
目标页面上的

为传递的参数创建令牌,并使用url令牌进行交叉检查。如果它匹配,则将其视为有效输入(您可以添加timstamp以生成令牌以获得更好的安全性)

答案 7 :(得分:0)

我只是建议使用POST而不是GET。

  

何时使用GET?

     

使用GET方法从表单发送的信息可见   每个人(所有变量名称和值都显示在URL中)。得到   对发送的信息量也有限制。限制   约有2000个字符。但是,因为显示了变量   在URL中,可以为页面添加书签。这可能很有用   有些情况。

     

GET可用于发送非敏感数据。

     

注意:绝不应将GET用于发送密码或其他密码   敏感信息!

     

何时使用POST?

     

使用POST方法从表单发送的信息是不可见的   其他(所有名称/值都嵌入在HTTP的主体中)   请求)并且对要发送的信息量没有限制。

     

此外,POST支持高级功能,例如支持   将文件上传到服务器时的多部分二进制输入。

     

但是,因为变量没有显示在URL中,所以不是   可以为页面添加书签。