web-dev-qa-db-ja.com

MVCモデルバインディングはWebサイトにどのような固有のリスクをもたらしますか?追加の警戒が必要ですか?

私が理解していることから、「モデルバインディング」は、ASP.NET MVCまたはRuby on Rails(他にもあります...) HTTPのGETステートメントのパラメータを使用して、サイト内のコードに変数として渡します。

GitHub(プログラマーに人気のFOSSサイト)がモデルバインディングのエクスプロイトを通じてハッキングされたため、この穴を閉じるために必要な一般的な方法を知りたいのですが。具体的には

  • モデルバインディングエクスプロイトとは何ですか?

  • すべてのMVCフレームワークは影響を受けますか?

  • これは開発者が対処する必要があるものですか...それともWebプロキシ/フィルターでこれを修正できますか?

  • 特定のサイトでこの問題を特定または診断するのに役立つセキュリティツールはありますか?

11

モデルバインディングは非常に優れた機能であり、適切に使用すると、全体的なセキュリティが向上する場合があります。

これがどのように機能するかです(コードと機能はASP.NET MVCに適用されますが、Rubyでも同じかもしれません):Webページにフォームがあるとします。

<form action="/SendData">

  Email: <input type="text" name="email" id="email"><br>
  Address:<input type="text" name="address" id="address"><br>

  <input type="submit" value="Submit">

</form>

あなたはこのようなクラスを書きます:

class Contact{
   String Email{get;set;} 
   String Address{get;set;} 
}

モデルバインディングを使用すると、ユーザー要求を処理する関数は次のようになります。

public ActionResult SendData(Contact contact){
        //do something with contact.Email and contact.Address
}

ご覧のとおり、モデルバインディングは、HTMLリクエストで受け取ったデータを、Contactタイプのオブジェクトに自動的に配置します。

さらに、DataAnnotationsを使用して検証関数を定義できます。

class Contact{
   [Required(ErrorMessage="Input email please!")]
   [RegularExpression("^some_regex"),ErrorMessage ="Error"]
   String Email{get;set;} 
   [Required(ErrorMEssage="Input address please!")]
   String Address{get;set;} 
}

次のように確認してください:

public ActionResult SendData(Contact contact){
    if(ModelState.IsValid)
    {
        //do something with contact.Email and contact.Address
    }
}

ご覧のとおり、検証といくつかの一般的な間違いを簡単に追加できます(不適切に記述されたSQLクエリなどは回避できます)。

次に、GitHubハック(マスバインディング)につながる問題を説明します。

フォームに表示されないクラスのプロパティがある場合はどうなりますか。

<form action="/SendData">

  Email: <input type="text" name="email" id="email"><br>
  <input type="submit" value="Submit">

</form>

攻撃者がaddressという名前の変数も送信した場合、フレームワークは、元の形式ではそのような入力がなかったことを知らずに、自動的にバインドします。

GitHubの場合、開発者はおそらく、管理者と通常のユーザーを区別するプロパティを持つオブジェクトを使用しました(isAdminなど)。このパラメーターをユーザーとパスワードと共にログインフォーム(または別のページ)で送信することにより、攻撃者は管理機能にアクセスする可能性があります。

この問題を解決する方法はいくつかあります(ブラックリストバインディング、ホワイトリストバインディング)が、フォームのプロパティのみを含む(または他の属性にread-onlyとマークされている)インターフェイスとクラスを使用することをお勧めします。

ホワイトリストバインディングの例:

public ActionResult SendData(
[Bind(Include="Email")]Contact contact)
{
    //...
}

影響を受けるフレームワークに関しては、おそらくほとんどが影響を受けますが(RubyとASPはそうです))、これは脆弱性自体ではなく、単に悪いプログラミングです。プログラマがこの機能に適切に対処している限り、すべて大丈夫です。

自動化されたツールでこの種の問題を検出できるとは思いませんが、徹底的なコードレビューで解決できるはずです。

5
Dinu

Dinuのコメントの更新として、多くの[〜#〜] php [〜#〜]フレームワークのモデルは、これと同じ種類の問題を抱えています。負荷から設定できない「制限されたプロパティ」を提供するものはほとんどありません。それらのほとんどは、値をそれらに "load()"するときに何をしているのかを知っていると仮定し、それに応じてプロパティを割り当てます-繰り返しになりますが、ずさんなコーディングプラクティスです。

Laravel 4は、大量割り当ての問題を防ぐための制限を提供するものだと私が見たものです。

1
enygma