是一種容許攻擊者經過受害者發送任意HTTP請求的一類攻擊方法。此處所指的受害者是一個不知情的同謀,全部的僞造請求都由他發起,而不是攻擊者。這樣,很你就很難肯定哪些請求是屬於跨站請求僞造攻擊php
以下表單瀏覽器
<form action="buy.php" method="POST"> <p> Item: <select name="item"> <option name="pen">pen</option> <option name="pencil">pencil</option> </select><br /> Quantity: <input type="text" name="quantity" /><br /> <input type="submit" value="Buy" /> </p> </form>
php請求處理安全
<?php session_start(); $clean = array(); if (isset($_REQUEST['item'] && isset($_REQUEST['quantity'])) { /* Filter Input ($_REQUEST['item'], $_REQUEST['quantity']) */ if (buy_item($clean['item'], $clean['quantity'])) { echo '<p>Thanks for your purchase.</p>'; } else { echo '<p>There was a problem with your order.</p>'; } } ?>
攻擊者嘗試使用get方式:http://store.example.org/buy.php?item=pen&quantity=1
若是能成功的話,攻擊者若是取得了當合法用戶訪問時,能夠引起購買的URL格式。在這種狀況下,進行跨站請求僞造攻擊很是容易,由於攻擊者只要引起受害者訪問該URL便可服務器
攻擊者並不須要取得用戶受權cookie
用戶再訪問其餘網站的時候,若是這個網站引導用戶發起了上面的請求,瀏覽器會帶上用戶相關的cookie,至關於非法網站取得了用戶受權。當你訪問http://www.google.com,你的瀏覽器首先會請求這個URL所標識的資源。你能夠經過查看該頁的源文件(HTML)的方式來看到該請求的返回內容。在瀏覽器解析了返回內容後發現了Google的標誌圖片。這個圖片是以HTML的img標籤表示的,該標籤的src屬性表示了圖片的URL。瀏覽器因而再發出對該圖片的請求,以上這兩次請求間的不一樣點只是URL的不一樣。session
根據上面的原理,跨站請求僞造攻擊能夠經過img標籤來實現。考慮一下若是訪問包括下面的源代碼的網頁會發生什麼狀況:
<img src="http://store.example.org/buy.php?item=pencil&quantity=50" />
ide
因爲buy.php腳本使用$_REQUEST而不是$_POST,這樣每個只要是登陸在store.example.org商店上的用戶就會經過請求該URL購買50支鉛筆。網站
跨站請求僞造攻擊的存在是不推薦使用$_REQUEST的緣由之一。google
生成表單tokencode
<?php session_start(); $token = md5(uniqid(rand(), TRUE)); $_SESSION['token'] = $token; $_SESSION['token_time'] = time(); ?>
提交表單的時候,token也之前提價到服務器。
<form action="buy.php" method="POST"> <input type="hidden" name="token" value="<?php echo $token; ?>" /> <p> Item: <select name="item"> <option name="pen">pen</option> <option name="pencil">pencil</option> </select><br /> Quantity: <input type="text" name="quantity" /><br /> <input type="submit" value="Buy" /> </p> </form>
一個跨站請求僞造攻擊就必須包括一個合法的驗證碼以徹底模仿表單提交。因爲驗證碼的保存在用戶的session中的,攻擊者必須對每一個受害者使用不一樣的驗證碼。這樣就有效的限制了對一個用戶的任何攻擊,它要求攻擊者獲取另一個用戶的合法驗證碼。使用你本身的驗證碼來僞造另一個用戶的請求是無效的。
該驗證碼能夠簡單地經過一個條件表達式來進行檢查:
<?php if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token']) { /* Valid Token */ } ?>
你還能對驗證碼加上一個有效時間限制,如5分鐘,而且讓token只能使用一次:
<?php $token_age = time() - $_SESSION['token_time']; $token = $_SESSION['token']; unset($_SESSION['token']); if ($token_age <= 300) { /* Less than five minutes has passed. */ } ?>
經過在你的表單中包括驗證碼,你事實上已經消除了跨站請求僞造攻擊的風險。能夠在任何須要執行操做的任何表單中使用這個流程。
你也可讓token只能使用一次,在每次請求被請求後token經過後銷燬這個token。能夠更安全,同時也能夠防止表單重複提交。使用cookei驗證
若是咱們不考慮用戶的Cookies很容易因爲網站中存在XSS漏洞而被偷竊(咱們已經知道這樣的事情並很多見)這一事實,這是一個很好的應對對CSRF的解決方案。若是咱們爲用戶的每個表單請求中都加入隨機的Cookies,那麼這種方法會變得更加安全,可是這並非十分合適
<?php // Hash the cookie $hash = md5($_COOKIE['cookie']); ?> <form method="POST" action="resolve.php"> <input type="text" name="first_name"> <input type="text" name="last_name"> <input type="hidden" name="check" value="<?=$hash;?>"> <input type="submit" name="submit" value="Submit"> </form> <?php // Check if the "check" var exists if(isset($_POST['check'])) { $hash = md5($_COOKIE['cookie']); // Check if the values coincide if($_POST['check'] == $hash) { do_something(); } else { echo "Malicious Request!"$$ } } else { echo "Malicious Request!"$$ } ?>
這個方案的思路是:每次的用戶提交都須要用戶在表單中填寫一個圖片上的隨機字符串,厄....這個方案能夠徹底解決CSRF,但我的以爲在易用性方面彷佛不是太好