7

我正在构建一个简单的 CRUD 应用程序(不使用 CRUD 模块)。

我的模型是一个具有一个属性的简单类。id 隐式继承自 Model。

@Entity
public class Account extends Model {

    @Required
    public String domain;
}

观点如下。请注意带有 id 的隐藏字段。

<form class="form-horizontal" action="@{Application.save}" method="POST">
<fieldset>
    <legend>Settings</legend>
    <input type="hidden" name="account.id" value="${account?.id}">

    #{field 'account.domain'}
    <div class="control-group #{if field.error != null} error #{/if}">
        <label class="control-label" for="${field.id}">&{field.name}</label>
        <div class="controls">
            <input type="text" class="input-xlarge" id="${field.id}" value="${field.value}" name="${field.name}">
            <span class="help-inline">${field.error}</span>
        </div>        
    </div>
    #{/field}        

    <div class="form-actions">
        <input class="btn btn-primary" type="submit" value="Save">
    </div>

</fieldset>

我已经能够构建一个保存、更新工作的场景。

完成更新的方式是我从隐藏字段中读取 ID,并更新记录。如果 ID 不可用,则会创建一条新记录。

所以问题是: ID 是否可以被破解,即修改,以便我将 1 更改为 2,并假设存在 2 的记录,它会被覆盖。(我想使用 firebug 或其他插件应该不难)。

我该如何防止这种情况?我想到的一个选项是读取具有给定 ID 的记录,如果允许用户修改它,我允许更新,否则不允许。这仍然不是万无一失的,因为虽然可以允许用户,但可以修改“错误”记录。

我想这是一个已知问题,希望有一个已知的解决方案。

感谢您花时间回答我的问题。

4

3 回答 3

9

所以问题是:ID 是否可以被破解,即修改,以便我将 1 更改为 2,并假设存在 2 的记录,它会被覆盖。(我想使用 firebug 或其他插件应该不难)。

我该如何防止这种情况?我想到的一个选项是读取具有给定 ID 的记录,如果允许用户修改它,我允许更新,否则不允许。这仍然不是万无一失的,因为虽然可以允许用户,但可以修改“错误”记录。

当然,攻击者可以更改记录的 id。

有几种方法可以最大限度地减少这种攻击的影响。

1)最简单的方法 -对象获取

从数据库中获取对象并检查它是否属于相关用户。这将防止其他用户弄乱不属于他们的对象,但不会阻止用户更改属于他的另一个对象。在大多数情况下,这是一种简单且足够的方法。

2)更复杂:签名

这里的想法是对您提供给模板的常量进行签名,并在表单提交后检查哈希是否仍然匹配。 这与 play 对其会话所做的非常相似。攻击者不可能弄乱常量(例如 id)并提供最大的安全性。但是,您将有更多工作要做。

例子:

    public static void someActionDisplayingForm(){
  SomeObject o = ....
  SomeOtherObject o2 = ....
      String constants = o.id + "|" + o2.id;
      String hash = Crypto.sign(constants);
       render(o, o2, hash);
}

在您拥有的模板中

 #{form ...}
   <input type='hidden' name='id1' value='${o.id}' />
   <input type='hidden' name='id2' value='${o2.id}' />
   <input type='hidden' name='hash' value='${hash}' />

在处理表格的方法中你会做

 public static void processing(String id1, String id2, String hash, String otherValues, ...){
   String constants = id1 + "|" + id2;
   String checkHash = Crypto.sign(constants);
    if(!checkHash.equals(hash))
     badRequest();
   ... 
}

希望有帮助。

于 2012-06-01T16:45:37.990 回答
2

ID 是否可以被破解,即修改,以便我将 1 更改为 2,并假设存在 2 的记录,它会被覆盖。(我想使用 firebug 或其他插件应该不难)。

你是对的。编辑这些内容就像在 Chrome 控制台中检查和编辑元素一样简单。记住; 客户端所做的任何事情都是不安全的,并且可以由用户修改。始终进行服务器端检查,始终.

我该如何防止这种情况?

一种可能的解决方法是将记录链接到用户,即,在用户和名为“recordAccess”的记录之间创建一个桥接表(或任何您的命名约定导致您调用它)。这个桥接表将有一个用户 ID 列和一个记录 ID 列。服务器将对照此表检查用户 ID 和记录 ID,并且仅当数据库中有匹配的行时才允许更改。如何向此表添加行取决于您的应用程序的工作方式,但应该不难解决。

为了防止用户编辑错误的记录,您可以在此桥接表中添加一个名为“current”(或者,再次,任何您喜欢的)的附加列,它是一个简单的布尔值。当用户去编辑他/她被允许编辑的记录时,该值将被设置为“true”,并且与该用户关联的所有其他行将被设置为“false”。然后,当用户提交编辑时,如果该行中的值设置为“true”,则该行成功更新并且值变回“false”。否则,所有值都设置为“false”并拒绝更新。

希望这能给你一些想法。

于 2012-06-01T02:03:16.257 回答
1

是的,可以修改。这样做不需要真正的知识或技能。在任何情况下,来自用户的信息在您进行其他验证之前都不得被信任。

为此,您需要某种服务器端逻辑。在许多情况下,这只是在服务器上链接到用户对象的会话,它允许您执行授权(您确保记录是他们可以修改的记录;哪个不太重要,并且是用户故意引起的错误,而不是安全风险)。

只要您可以将请求绑定回用户,然后确保允许用户执行请求,就可以了。最简单的方法通常是会话,但空间很大。

于 2012-06-01T01:54:13.023 回答