この記事は主に yii2 における CSRF 攻撃に対する予防策を紹介します。これには一定の参考価値があります。今、あなたに共有します。困っている友達は参考にしてください。
今日、Bei 兄弟がこれを普及させます。 csrfとは何ですか?すでにご存知の場合は、記事の一番下までスクロールして「いいね」を押してください。
CSRF (クロスサイト リクエスト フォージェリ) は、Web サイトの悪意のある使用であり、2007 年のインターネット セキュリティの脅威トップ 20 の 1 つとしてリストされています。隠れた危険。
CSRF に関しては、物語から始めなければなりません~
この物語は、プログラマーの老王が 10,000 元を失ったことから始まります。泥棒だったが、無駄に回収された。お金を失った後、ラオ・ワンさんは考え続けました。どうして彼はお金を失ったのか、なぜ彼はお金を失ったのか、なぜ私はお金を失ったのか~~
その後、ラオ・ワンさんは深刻な症状に陥りました。精神的な問題を抱え、社会に復讐することを決意した。
Lao Wang 氏は最初にオンライン バンキング システムを調査し、送金が GET
https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=abei
の形式であることを発見しました。これは、liuxiaoer からの 1,000 元が送金されたことを意味します。もちろん、リクエストが銀行サーバーに到達すると、プログラムはリクエストが正当なセッションからのものであり、セッションのユーザーが liuxiaoer でログインしているかどうかを確認します。 。 Lao Wang 自身も銀行口座を持っています
wang2。彼はログインを試み、ブラウザを通じて銀行にリクエストを送信しました。コードは次のとおりです。https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=wang2
つまり、この作戦は
liuxiaoerが行う必要があります。復讐の力は恐ろしいものです。Lao Wang は Facebook を通じて liuxiaoer を見つけました。これは宅配業者の Lao ですWang Liu の銀行口座番号。
それで素晴らしい計画が生まれました。老王の計画は次のようなものでした。1. まず Web ページを作成し、次のコードを Web ページ
src="https://bank.abc.com/withdraw?account=liuxiaoer&amount=1000&to=wang2"
に追加して、Liu (liuxiaoer) がさまざまなシナリオを通じてこの Web ページにアクセスできるようにします。
2. Lao Liu (liuxiaoer) がこの Web ページにアクセスすると、上記のリクエストが銀行に送信され、この時点で Lao Liu (liuxiaoer) 自身のブラウザの Cookie 情報も含まれます。もちろん、これは通常は当てはまりませんが、銀行サーバーは Liu (liuxiaoer) がログインしていないことを検出するため、成功します。
3. ラオ・ワンはあるトリックを思いつきました。タオバオで灰色のビジネスマン、ラオ・リーを見つけ、さまざまな方法を使うように頼みました。つまり、彼はラオ・リウ (liuxiaoer) に、金融機関を通じてラオ・リーに送金するよう依頼しました。ブラウザ。
4. 3 番目のステップから 2 分以内に、Lao Wang は Lao Liu (liuxiaoer) に、自分が作成した Web ページに再度アクセスするよう依頼することに成功しました。ご存じのとおり、Lao Liu (liuxiaoer) はその時点で銀行にいました。セッションの有効期限が切れていません。Lao Wang の Web ページが銀行サーバーにリクエストを送信した後、検証に合格し、支払いが成功しました。
5. Lao Wang が支払いを受け取りました。Lao Liu (liuxiaoer) はこのすべてを知りませんでした。銀行にとって、これは通常の送金でした。
これは CSRF 攻撃であり、ブラウザはこれを傍受できません。CSRF 攻撃の特徴
CSRF 防御ソリューション
この方法は最も単純で、ビジネス コードを変更する必要がなく、サーバーに到着する各リクエストをインターセプトして分析するだけで済みます。
しかし、Referer の値はブラウザーに属するため、このメソッドの欠点も明らかです。HTTP プロトコルでは変更が許可されていませんが、ブラウザー自体に抜け穴がある場合、Referer が
安全ではありません。たとえば、IE6 はメソッドを通じて Referer 値を改ざんできます。
この方法は最新のブラウザでも絶対に利用できるわけではありません。ユーザーのプライバシーに関わるものです。多くのユーザーはブラウザでリファラーを提供しないように設定しているため、サーバーがリファラーを取得できない場合にむやみにリファラーを提供することはできません。サービスを拒否してください。これは正当なリクエストである可能性があります。
CSRF攻击之所以能成功,是因为黑客完全伪造了一次用户的正常请求(这也是浏览器无法拦截的原因),并且cookie信息就是用户自己的,那么我们如果在请求中放入一些黑客无法去伪造的信息(不存在与cookie中),不就可以抵御了么!
比如在请求前生成一个token放到session中,当请求发生时,将token从session拿出来和请求提交过来的token进行对比,如果相等则认证通过,否则拒绝。token时刻在变化,黑客无法去伪造。
针对于不同类型的请求一般方案是
GET 放到url中,比如http://url?csrftoken=xxxx
POST 放到表单的隐藏域
对于GET请求,这里有一点要说明,在一个网站中请求的url很多,一般情况我们是通过js对dom的所有节点进行遍历,发现a链接就在其href中增加token。
这里存在一个问题,比如黑客将自己网站的链接发到了要攻击页面,则黑客网站链接后面会有一个token,此刻客户可以通过编写自己网站代码得到这个token,然后用这个token立刻构造表单,发起CSRF攻击,因此在js遍历的时候,如果发现不是本站的链接,可以不加token。
这个方法在思路上和上面的token方式一样,只不过将token放到了HTTP头部中,不再参数传递,通过XMLHttpRequest类可以一次性的给所有请求加上csrftoken这个HTTP头属性并设置值。
这种方法适合上面批量添加token不方便的情况,一次性操作,不过局限性也比较大,XMLHttpRequest请求通常用在ajax方法中,并非所有请求都适合。
首先要说的是每种CSRF防范措施都有其弊端,无论你的防范多么严密,黑客拥有更多的攻击手段,因此在重要逻辑上(必须写入和删除)必须非常小心,接下来我们把yii2框架在csrf上的部署说一下。
我们以yii2.0.14为解说版本。
在CSRF这块,yii2框架采取了HTTP头部和参数token并行的方式,针对于每个请求,在beforeAction都会做一次判断,如下
// vendor/yiisoft/yii2/web/Controller.php public function beforeAction($action) { if (parent::beforeAction($action)) { if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !Yii::$app->getRequest()->validateCsrfToken()) { throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.')); } return true; } return false; }
如果我们没有设置 enableCsrfValidation 为false,并且没有报错,则会进行csrf验证,核心方法就是
Yii::$app->getRequest()->validateCsrfToken()
该方法存在于 vendor/yiisoft/yii2/web/Request.php 中,我们看一看它。
public function validateCsrfToken($clientSuppliedToken = null) { // 省略上面代码 return $this->validateCsrfTokenInternal($this->getBodyParam($this->csrfParam), $trueToken) || $this->validateCsrfTokenInternal($this->getCsrfTokenFromHeader(), $trueToken); }
validateCsrfToken函数代码我们只需要看最后的返回,getBodyParam或getCsrfTokenFromHeader方法得到的token,只要有一种验证通过,就认为合法。
以上是整体的思路,为了让你看的更清晰,我画一个图并增加一些名词解释。
以上是yii2的csrf策略部署,当然我还是推荐你使用 xdebug等调试工具 一步一步看看这个过程。
最后我在把上图的关键函数进行说明
generateCsrfToken() 该函数生成token并存到cookie或session中,该值不会随页面刷新而变化,它更多充当钥匙的作用,根绝它生成具体的csrfToken。
getCsrfToken() 生成具体的csrfToken,就是你在表单隐藏域中看到的那个值,这个值将来会传到服务器和真实的csrfToken进行对比,验证是否合法。
validateCsrfToken() 进行合法性验证,该函数得到一个真实的csrfToken然后和客户端上传来的csrfToken进行对比。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
以上がyii2 の CSRF 攻撃に対する予防策の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。