2009-10-01 20 views
5

私はカレンダーのようなASP.NET MVCアプリケーションを持っています。 NerdDinnerの例では、UpdateMethod()を使用して編集ページの結果を更新しています。ASP.NET MVC UpdateModelはハッキングに対して脆弱ですか?

私のアプリでは、特定のイベントは完全にカスタマイズ可能であり、特定のものは部分的にしかカスタマイズできません。部分的にカスタマイズ可能なイベントを編集するための編集フォームは、それらのフィールドしか利用できませんが、明らかに、誰かが欠落したデータで自分のフォームを作成し、自分のサイトに投稿する可能性があります。彼らがそうしているなら、誰かがどんな/すべてのフィールドを変えないようにするのでしょうか?さらに悪いことに、id(主キー)を変更しようとするとどうなりますか?

UpdateModel()は非常に基本的なハッキングに対して脆弱です。私の恐怖は正当なものか、私が紛失しているものがありますか?

// POST: /MyEvents/Edit/2 
[AcceptVerbs(HttpVerbs.Post), Authorize] 
public ActionResult Edit(int id, FormCollection formValues) 
{ 
    MyEvent myevent = eventRepository.GetMyEvent(id); 

    try 
    { 
     UpdateModel(myevent); 
     eventRepository.Save(); 
     return RedirectToAction("Details", new { id = myevent.MyEventId }); 
    } 
    catch 
    { 
     ModelState.AddRuleViolations(myevent.GetRuleViolations()); 
     return View(new MyEventFormViewModel(myevent)); 
    } 
} 
+0

easy/safe mode =フォーム(in)モデルを作成し、Automapperを使用してエンティティにマップします。 – mxmissile

答えて

9

"モデルバインディングのセキュリティ"に関するセクションがありません。ユーザーの入力方法によって更新できるプロパティのホワイトリストを常に含める必要があります。例えば

、NerdDinnerから:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Include="Title, Address")] Dinner dinner) 
{ 

} 

か、のUpdateModelを呼び出している場合、あなたは許さプロパティの文字列配列を作成し、あなたがクラスをロックダウンすることができます

UpdateModel(myObject, allowedProperties); 

を行うことができます特定のプロパティだけが更新可能であるようにします。

[Bind(Include="MyProp1,MyProp2,MyProp3")] 
public partial class MyEntity { } 
+0

データ入力画面に20または30の要素があるまでは痛み=) –

+2

ブラックリストを使用することもできます:) – womp

7

あなたの恐怖は正しいです。これは質量割り当てと呼ばれます。クラスをBindAttributeに設定し、Exclude/Includeのプロパティを設定することで、コードを保護することができます。

1

UpdateModelのオーバーロードは、更新する文字列の名前付けプロパティの配列をとります。これらのオーバーロードは、名前付きプロパティのみを更新します。

これを達成するための他のより簡単な宣言的な方法がありますが、私はMVCデータバインディングの専門家ではありません。

1

更新で無視する必要があるモデルのフィールドにマークを付けることも、包含/除外フィールドのリストを他のUpdateModelオーバーロードの1つを使用して渡すこともできます。

4

あなたのモデルの任意のプロパティにフィールドをマッピングすることは、企業内/悪意のある人には完全に可能です。これにはいくつかの方法があります

最も簡単なのは、前述のようにUpdateModelのexclude/includeプロパティオーバーロードを使用することです。これの欠点は、メソッドが文字列配列を受け付けるだけで、名前を変更した場合にコードが同期しなくなることがあることです。

もう1つの方法は、バインドされたフィールドを保持する単純なDTOを使用することです。次に、DTOを使用してイベントオブジェクトを使用して別のクラスを追加します。これははるかに手作業ですが、コントロール

public ActionResult(int id, EditForm form) { 
    MyEvent event = _eventRepository.GetMyEvent(id); 
    event.Name = form.Name; //etc; 
    if (User.IsInRole("Organiser")) { 
     event.Date = form.Date; 
    } 
    return ... 
} 

もう1つの方法は、希望のフィールドのみをバインドするMyEventクラス用の顧客モデルバインダーを使用することです。

関連する問題