背景
最近公司安全部對我負責的web模板進行了安全測試舅巷,提出了很多安全問題套硼,里面有一項是跨站攻擊垫毙,優(yōu)先級比較高霹疫,因此對這種攻擊方式進行了研究。我們的使用的laravel框架综芥,因此最后的解決方案是用php寫的丽蝎,其他語言可以自己實現(xiàn)下,原理一樣膀藐。
一屠阻、CSRF攻擊原理
英文名稱:Cross-site request forgery 中文名稱:跨站請求偽造 縮寫:csrf/xcsrf。簡單說就是是用戶登錄目標網(wǎng)站后额各,誘騙用戶點擊攻擊界面国觉,然后偽造用戶請求,實現(xiàn)攻擊虾啦。
簡易轉(zhuǎn)賬的攻擊例子:
說明:
訪問A網(wǎng)站后麻诀,沒有退出的情況下cookie會被保留。步驟4中請求A網(wǎng)站缸逃,通過修改轉(zhuǎn)賬用戶和金額针饥,會重新提交轉(zhuǎn)賬請求,由于cookie未過期需频,轉(zhuǎn)賬成功丁眼。
二、攻擊模擬
開發(fā)防御代碼昭殉,必須要在模擬攻擊方式苞七,這里有個神器burpsuit
1.proxy->intercept 設(shè)置為 is off
2.設(shè)置代理
3.設(shè)置搜狐瀏覽器(chrome也可以,需要安全插件)
4.找到常規(guī)-》網(wǎng)絡(luò)設(shè)置-》手動配置代理挪丢,與burpsuit中的一致
點擊test in browser蹂风,如果在瀏覽器中請求成功了說明存在csrf漏洞
三、偽造的網(wǎng)站能獲取哪些信息
- 轉(zhuǎn)賬鏈接乾蓬。通過charles抓包可以獲取
- 請求方法和參數(shù)名:post和get
這些是攻擊的前提惠啄,在生成廣告鏈接G之前這些是提前準備好的。 -
無法獲取到信息:cookie。
這里簡單說下 瀏覽器同源策略
官方文檔 https://tools.ietf.org/html/rfc6454撵渡,這里說明了必須
scheme, host和 port必須完全一致才是同源融柬,同源才可以訪問cookie等信息。為了舉例趋距,下面的表格給出了與URLhttp://www.example.com/dir/page.html"的對比粒氧。
Screen Shot 2019-03-28 at 12.10.22 AM.png
四、防御方案
1节腐、添加驗證碼
這種方式可以防止csrf攻擊外盯,但是成本高。一般是用在登錄翼雀、短信等不頻繁的操作界面饱苟。
2、驗證http的refer
http的refer顯示了網(wǎng)站的來源狼渊,但是http refer可以被關(guān)閉掷空,不能保證可以獲取到(例如IE)
3、token驗證
原理:既然網(wǎng)站B不能訪問到網(wǎng)站A的cookie囤锉,那么我們可以在請求中添加cookie的token進行安全校驗。
具體操作是:服務(wù)端生成token放在cookie中护锤,user 訪問A網(wǎng)站都要帶上公共參數(shù)token官地,token來自cookie,服務(wù)端校驗token和session中的token是否一致烙懦,不一致則是非法操作驱入。
前后端分離情況下示例代碼:
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
'XSRF-TOKEN',
];
}
這個是laravel的cookie加密中間件,為了使用方便移除token的加密(官網(wǎng)未加密token是放在html中的)氯析,顯然沒必要加密
前端代碼:
var token = getCookie("XSRF-TOKEN")
$.ajax({
//幾個參數(shù)需要注意一下
type: "POST",//方法類型
dataType: "json",//預(yù)期服務(wù)器返回的數(shù)據(jù)類型
url: "/transfer" ,//url
headers:
{
"X-CSRF-TOKEN": token
},
data: $('#Form').serialize(),
success: function (result) {
window.location = '[http://test.com:8000/success](http://test.com:8000/success)'
console.log(result);//打印服務(wù)端返回的數(shù)據(jù)(調(diào)試用)
},
error : function() {
alert("異常亏较!");
}
});
再次用burpsuit測試,發(fā)現(xiàn)頁面已不能訪問成功掩缓。
csrf防御成功雪情!
4、jwt 方式登錄和授權(quán)
一般攻擊的地方都是需要登錄驗證的你辣,因此可以在登錄驗證方式上進行防御巡通。
- 客戶端使用賬戶密碼請求登錄接口
- 登錄成功后服務(wù)器使用簽名密鑰生成JWT ,然后返回JWT給客戶端
- 客戶端再次向服務(wù)端請求其他接口時帶上JWT
- 服務(wù)端接收到JWT后驗證簽名的有效性.對客戶端做出相應(yīng)的響應(yīng)
token是存在客服端的,可以是cookie或者localstorage等舍哄⊙缌梗客戶端請求服務(wù)端一般會把token放在header中,這就天然的防止了跨域攻擊表悬。jwt的具體使用可以參考這篇文章弥锄。如果項目還沒開始,建議使用使用這種方式進行登錄授權(quán),而且方便后期sso籽暇。