web-dev-qa-db-ja.com

PHP=のCSRF(クロスサイトリクエストフォージェリ)攻撃の例と防止

私は人々がこのような投票をすることができるウェブサイトを持っています:

http://mysite.com/vote/25

これにより、項目25に投票が行われます。登録ユーザーのみが利用できるようにしたいのです。今、私は誰かがウェブサイトで忙しいときを知っており、誰かが次のようなリンクを与えます:

http://mysite.com/vote/30

投票は、彼がこれを行うことを望まずに、アイテムに対する彼のための場所になります。

OWASP Webサイトの説明 を読みましたが、実際には理解していません

これはCSRFの例であり、これを防ぐ方法はありますか。考えられる最善のことは、ハッシュのようなものをリンクに追加することです。しかし、これはすべてのリンクの最後に何かを置くのは非常にイライラするでしょう。これを行う他の方法はありません。

ウェブサイトは私にとってかなり気まずいように見えるので、別のことが誰かにこの他の例を与えるかもしれません。

49
Saif Bechan

次の場合、これはCSRFの例になります。

  • そのリンクがフェッチされます(たとえば_<img>_タグを介して):偽造
  • 別のサイトから:クロスサイト


たとえば、この_<img>_タグをstackoverflowのHTMLソースコードに挿入できた場合(また、stackoverflowでは、彼の中で_<img>_タグを使用できるため、投稿)

_<img src="http://mysite.com/vote/30" />
_

あなたはその項目に投票したでしょう;-)


一般的に使用される解決策は、URLに有効期間が制限されたトークンを配置し、URLが取得されたら、このトークンがまだ有効であることを確認することです。

基本的な考え方は次のとおりです。

  • ページを生成する場合:
    • 一意のトークンを生成する
    • ユーザーのセッションに保存します
    • ページのリンクに配置します-これは次のようになります:_http://mysite.com/vote/30?token=AZERTYUHQNWGST_
  • 投票ページが呼び出された場合:
    • トークンがURLに存在するかどうかを確認します
    • ユーザーのセッションに存在するかどうかを確認します
    • そうでない場合=>投票を登録しないでください

そこにあるアイデアは:

  • トークンの寿命は長くないため、推測が困難です
  • つまり、あなたの攻撃者
    • 彼の注射が有効になる数分間の窓しかありません
    • 推測が上手でなければなりません^^
    • ユーザーごとに異なるページを生成する必要があります。


また、ユーザーがサイトを離れた後もユーザーのセッションがアクティブになっている時間が短いほど、ユーザーが悪いWebサイトにアクセスしたときに有効であるというリスクが少なくなります。

しかし、ここでは、セキュリティとユーザーフレンドリーを選択する必要があります...


別のアイデア(それは完全に安全ではありませんが、POSTリクエストを強制する方法がわからない人には役立ちます)、POST人々が投票しているときのリクエスト:

  • ブラウザは、挿入されたタグのGETリクエストを送信しています
  • とにかく、このURLは一部のデータを変更しているため、GETでは機能せず、POSTでのみ機能するはずです。

しかし、これは完全に安全ではないことに注意してください。(おそらく?)少しのJavaScriptでPOSTリクエストを強制/偽造することが可能です。

91
Pascal MARTIN

まず、GETリクエストを使用してサーバーの状態を変更するべきではないため、投票サービスではPOST/PUTをお勧めします。これは単なるガイドラインですが、賢いものです。

あなたの質問に、CSRFはクライアントの問題なので、どの種類のサーバー言語(あなたの場合はPHP)を使用してもかまいません。標準的な修正は同じで、次のようになります。URI/ POST-dataにランダムな値を、Cookieヘッダーに同じ値を設定します。それらが一致する場合、CSRFがないことを確認できます。 StackOverflowの例では、これをどのように行うことができるかについて、多くの情報があります。 これ
がんばろう!

19
MyGGaN

OWASPには、PHPのCSRFGuardと、PHPのXMB-> UltimaBB-> GaiaBBのためにずっと前に書いたもののESAPIがあります。

http://code.google.com/p/gaiabb-olpc/source/search?q=function+get_new_token&origq=function+get_new_token&btnG=Search+Trunk

他の人がそのコードをクリーンアップし、より強力なトークンを許可したようです:

https://www.owasp.org/index.php/PHP_CSRF_Guard

ありがとう、アンドリュー

5
vanderaj

CSRF攻撃には3人のプレイヤーがいます

  1. 被害者のWebサイト(例では投票Webサイト)[ログインしているユーザーのCookieを知っています]
  2. クライアントのブラウザー(ログイン中)[Cookieを知っている]
  3. 攻撃者のWebサイト[ログインしているユーザーのCookieを知らない]

CSRF攻撃は2つの事実に依存しています

  1. ブラウザはリクエストごとに自動的にクッキーを送信します
  2. ログインユーザーを識別するためにCookieに依存しています(例:setcookie("sessionID", "0123456789ABCDEF", time()+3600);

攻撃者が不在の場合、または別のユーザーがログインユーザーにこれを要求した場合

// http://victim.website/vote/30

たとえば、攻撃者のWebサイトにリンクを配置するか、メールで送信すると、ログインしたクライアントブラウザーは、このリクエストとともに識別Cookie(sessionID)を送信します。これにより、被害者のWebサイトは、ログインしたユーザーが本当に投票する!

しかし、被害者のWebサイトがより賢く、追加のGETまたはPOSTパラメーター(Cookieではない)でログインユーザーのリクエストを検証する場合、GETおよびPOSTパラメータはブラウザによって自動的に送信されないため、推測する必要があります。

// http://victim.website/vote/30?csrfSecret=0123456789ABCDEF

攻撃者はcsrfSecretパラメーターを知らないため、これは被害者のWebサイトとクライアント(セッショントークンのように)の間の秘密であるため、攻撃者はリクエストを偽造したいURLを作成する方法がありません。 。

同様に、投票がPOST要求によって行われた場合、攻撃者は被害者の秘密を知らないため、自分のWebサイト(またはサードパーティのWebサイト)でフォームを作成できません。ウェブサイトと彼のユーザー。

<form method="post" action="http://victim.website/vote" >
    <input type="hidden" name="vote" value="30">
    <input type="hidden" name="csrfSecret" value="????? I don't know it :(">
</form>
1
Accountant م