7

私は単純な CRUD アプリを構築しています (CRUD モジュールを使用していません)。

私のモデルは、1 つの属性を持つ単純なクラスです。ID はモデルから暗黙的に継承されます。

@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 や他のプラグインでは難しくないと思います)。

これを防ぐにはどうすればよいですか?私が考えた1つのオプションは、指定されたIDでレコードを読み取ることです。ユーザーが変更を許可されている場合は更新を許可し、そうでない場合は許可しません。ユーザーが許可されても、「間違った」レコードが変更される可能性があるため、これはまだ確実ではありません。

これは既知の問題であり、うまくいけば既知の解決策があると思います。

私の質問に答えてくれてありがとう。

4

3 に答える 3

9

問題は、ID をハッキング、つまり変更して 1 を 2 に変更できるかどうかです。2 のレコードが存在すると仮定すると、それは上書きされます。(firebug や他のプラグインでは難しくないと思います)。

これを防ぐにはどうすればよいですか?私が考えた1つのオプションは、指定された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 のコンソールで要素を調べて編集するのと同じくらい簡単です。覚えて; クライアント側で行われることはすべて安全ではなく、ユーザーが変更できます。常にサーバー側のチェックを行います。

これを防ぐにはどうすればよいですか?

考えられる解決策の 1 つは、レコードをユーザーにリンクすることです。つまり、"recordAccess" と呼ばれるユーザーとレコードの間のブリッジ テーブルを作成します (または命名規則によって呼び出されるものは何でも)。このブリッジ テーブルには、ユーザー ID 列とレコード ID 列があります。サーバーはこのテーブルに対してユーザー ID とレコード ID をチェックし、データベースに一致する行がある場合にのみ変更を許可します。このテーブルに行を追加する方法は、アプリの動作によって異なりますが、難しいことではありません。

ユーザーが間違ったレコードを編集するのを防ぐために、単純なブール値である "current" (または、好きなもの) と呼ばれるこのブリッジング テーブルに追加の列を追加できます。ユーザーが編集を許可されているレコードを編集しようとすると、この値は「true」に設定され、そのユーザーに関連付けられている他のすべての行は「false」に設定されます。次に、ユーザーが編集を送信したときに、その行の値が「true」に設定されている場合、行は正常に更新され、値は「false」に戻ります。それ以外の場合、すべての値が「false」に設定され、更新は拒否されます。

うまくいけば、これでいくつかのアイデアが得られます。

于 2012-06-01T02:03:16.257 に答える
1

はい、変更できます。そうするのに本当の知識やスキルは必要ありません。いずれにせよ、ユーザーからの情報は、別の方法で検証するまで信頼してはなりません。

そのためには、ある種のサーバー側ロジックが必要です。多くの場合、これはサーバー上でユーザー オブジェクトにリンクされた単なるセッションであり、これにより承認を実行できます (レコードが変更可能なものであることを確認します。どちらが重要でなく、意図的にユーザーが引き起こしたバグであり、問​​題ではありません)。セキュリティリスク)。

リクエストをユーザーに関連付けることができれば、ユーザーがリクエストの実行を許可されていることを確認できれば問題ありません。これを行う最も簡単な方法は通常セッションですが、多くの余地があります。

于 2012-06-01T01:54:13.023 に答える