問題
Breeze に変更を保存するときに、サーバー側で実装する必要がある独自のセキュリティの量を正確に把握しようとしています。特に、悪意のあるユーザーが SaveChanges リクエストを手動でハッキングしたり、クライアントの JavaScript をハッキングしたりして、通常のビジネス ルールをバイパスする方法を考えています。たとえば、エンティティの外部キー ID を悪意を持って変更するなどです。
セキュリティの取り組みをどこに集中させる必要があるかを正確に理解したい。不要なセキュリティ層を実装するために時間を無駄にしたくありません。
サーバー側で .net および Entity Framework と共に Breeze を使用しています。
例
これは簡単な例です。ObjectA
への参照がありObjectB
、ObjectA
特定の によって所有されていUser
ます。したがって、私のデータベースは次のようになります。
ObjectA:
Id ObjectB_Id SomeField User_Id
1 1 Alice's ObjectA 1
2 2 Bob's ObjectA 2
ObjectB:
Id SomeOtherField
1 Foo
2 Bar
User:
Id Name
1 Alice
2 Bob
このモデルから、私が持っているセキュリティ上の懸念は次のとおりです。
- 認証されていないユーザーにデータを変更させたくない
- Bob が Alice の
ObjectA
- アリスに
ObjectA
ボブのObjectB
. User_Id
ボブが自分ObjectA
をアリスに変えようとしてほしくありません。
(1) の解決策は自明です。SaveChanges メソッドに[Authorize]
属性があることを確認します。
問題 2 から 4 を再現するために、Fiddler を使用して SaveChanges 要求を簡単に作成できます。たとえば、Alice
の ObjectA を Bob の を指すように変更する要求を作成できObjectB
ます。メッセージの内容は次のようになります。
"entities":
[
{
"Id":1,
"ObjectB_Id":2,
"SomeField":"Alice's ObjectA",
"User_Id":1,
"entityAspect":
{
"entityTypeName":"ObjectA:#MyNamespace",
"defaultResourceName":"ObjectAs",
"entityState":"Modified",
"originalValuesMap":
{
"ObjectB_Id":"1"
},
"autoGeneratedKey":
{
"propertyName":"Id",
"autoGeneratedKeyType":"Identity"
}
}
}
],
予想通り、サーバー側にセキュリティが実装されていない場合、更新されObjectB_Id
た値がデータベースに保持されます。
ObjectB_Id
ただし、 にのエントリがない場合、メッセージの本文で のoriginalValuesMap
値を変更しても、データベースに更新されないことも確認しました。ObjectB_Id
一般的なルール?
したがって、これは、サーバーで従う必要がある一般的なセキュリティ規則が次のとおりであることを意味すると思います。
[2013 年 7 月 4 日に編集 - わかりやすくするために書き直しました]
一般に:
- メッセージ内の何も信頼できません: originalValuesMap の値も、おそらく「変更されていない」値もありません。
- 唯一の例外はエンティティの ID であり、これは正しいと想定できます。
- おそらく「変更されていない」プロパティは、元のValuesMapになくても改ざんされている可能性があります
「変更されていない」プロパティ (originalValuesMap にもないプロパティ) の場合:
- 「変更されていない」プロパティを「使用する」場合、メッセージの値を使用してはなりません。データベースからオブジェクトを取得し、その値を使用する必要があります。
- たとえば、オブジェクトの所有権をチェックして、ユーザーがオブジェクトを変更できることを確認する場合、メッセージの UserId を信頼することはできません。データベースからエンティティを取得し、そこから UserId 値を使用する必要があります
- まったく使用していないその他の「変更されていない」プロパティについては、改ざんされていても心配する必要はありません。
変更されたプロパティ (originalValuesMap にもあるプロパティ) の場合:
ビジネス ルールによって、特定のプロパティの変更が妨げられる場合があります。この場合、そのようなルールごとにチェックを実装する必要があります。
値の変更が許可されていて、それが外部キーである場合は、セキュリティ チェックを実行して、新しい値がセッション ID で使用できることを確認する必要があります。
これらは改ざんされている可能性があるため、originalValuesMap の元の値は使用しないでください。
【編集終わり】
ルールの実装
これらのルールが正しいと仮定すると、変更された外部キーにセキュリティを実装するためのオプションがいくつかあると思います。
- ビジネス ルールで特定のフィールドの変更が許可されていない場合は、SaveChanges リクエストを拒否します
- ビジネス ルールで特定のフィールドの変更が許可されている場合は、新しい値が許可されていることを確認します。これを行う際に、
originalValuesMap
;は使用できません。データベース (またはセッション Cookie などの他の信頼できるソース) にアクセスする必要があります。
これらのルールを上で述べたセキュリティ上の問題に適用すると、
セキュリティ上の懸念 (2)。セッションのユーザー ID を、現在データベースにある
User_ID
と照合する必要があります。ObjectA
これは、リクエストに User_ID が含まれていなくても、その User_ID を信頼できないためですoriginalValuesMap
。セキュリティ上の懸念 (3)。ビジネス ルールで の変更が許可されている場合、
ObjectB
の新しい値の所有者を確認する必要がありObjectB_Id
ます。これを行うには、指定された ObjectB をデータベースから取得します。これが の所有者でObjectB
はない場合ObjectA
、おそらく変更を拒否したいと思います。セキュリティ上の懸念 (4)。ビジネス ルールで の変更が許可されている場合
User
、これは (2) で既にカバーされています。
質問
だから、本当に、私は正しい方向に沿って考えているという確認を探しています.
- 私の一般的なルールは正しいですか?
- ルールの実装は合理的に聞こえますか?
- 何か不足していますか?
- 私は物事を複雑にしすぎていますか?