注意安全(2)综慎!XSRF跨站偽造請(qǐng)求

上一篇我們說(shuō)了用腳本注入去公雞小熊哥的博文評(píng)論莱找。普通的腳本注入很容易就被前端后臺(tái)全方位的腳本過(guò)濾給處理掉酬姆,完全沒(méi)有殺傷力。一般來(lái)說(shuō)遇到<, > , =" 等等可能加載執(zhí)行腳本的用戶輸入宋距,轉(zhuǎn)換為&lt ; & gt ; 等等即可作為數(shù)據(jù)打印到 DOM 中轴踱,而不是作為腳本執(zhí)行。詳細(xì)情況參考上一篇文章 谚赎。我敢保證淫僻,@Swanky 肯定是受了我的蠱惑去 POST 了 三萬(wàn)多條評(píng)論導(dǎo)致被 @簡(jiǎn)書首席封號(hào)官 封號(hào)了。

偽造請(qǐng)求的過(guò)程


這次來(lái)說(shuō)說(shuō)偽造公雞(Cross Site Request Forgery)的事情壶唤。通俗點(diǎn)講就是 有人給你發(fā)送了一個(gè)鏈接雳灵,然后你手賤點(diǎn)開,是看起來(lái)很正常的網(wǎng)頁(yè)(A.com/index.html)闸盔,結(jié)果暗中被發(fā)送了一個(gè)指向 招商銀行轉(zhuǎn)賬服務(wù)(B.com/transfer) 的POST請(qǐng)求悯辙,這個(gè)請(qǐng)求是攻擊者在A.com/index.html 腳本中偽造的,因此請(qǐng)求的發(fā)送方屬于A.com域迎吵,而不屬于B.com/transfer 的域躲撰, 所以叫做 跨站偽造請(qǐng)求

// attack.html. 為了在這個(gè)偽造的網(wǎng)頁(yè)中自動(dòng)發(fā)送請(qǐng)求并且?guī)?受害用戶的cookie,
// 一般都會(huì)在hidden iframe中加載一份正規(guī)網(wǎng)站的頁(yè)面击费,而且攻擊表單也是隱藏的拢蛋。
// 表面上這個(gè)偽造網(wǎng)頁(yè)是很正規(guī)的,并無(wú)異常蔫巩。
  <form id="thisForm" method="POST" target="_blank" action="http://www.bank.com/transfer">
        <input type="text" name="name" value="csrf_Attack2!!!">
  </form>
  <iframe name="tab" src="http://www.bank.com" style="display:none;"> 
  </iframe> 

XSRF 原理


XSRF的關(guān)鍵就是 假如正規(guī)網(wǎng)站(B.com)的服務(wù)器端沒(méi)有防御機(jī)制谆棱,只是對(duì)于發(fā)來(lái)的請(qǐng)求做用戶身份驗(yàn)證,那么偽造請(qǐng)求就可以借用受害者瀏覽器自動(dòng)發(fā)送的cookie蒙混過(guò)關(guān)圆仔,實(shí)行惡意攻擊垃瞧。其中有幾個(gè)問(wèn)題需要明確:

  1. 用戶身份信息一般通過(guò)Http Request 的頭部cookie 字段的值來(lái)傳遞,cookie中往往包含sessionid 這樣的用戶會(huì)話信息坪郭,服務(wù)器通過(guò)比對(duì)服務(wù)端內(nèi)存或數(shù)據(jù)庫(kù)(Redis等)中維持的session就可以知道是哪個(gè)用戶在發(fā)請(qǐng)求个从,Session有無(wú)過(guò)期。 這一過(guò)程一般不驗(yàn)證請(qǐng)求發(fā)送方的 域歪沃。
  2. 跨站偽造請(qǐng)求成功的前提是 B.com 提供了可供跨域調(diào)用的服務(wù)信姓。因?yàn)槲覀冎来蟛糠譃g覽器和服務(wù)器都禁止腳本請(qǐng)求跨域資源,這種行為一般不太安全绸罗。但是我非得請(qǐng)求呢意推?? 所以除了用JSONP 來(lái)GET跨域資源珊蟀,更有采用CORS(Cross-origin resource sharing菊值,跨域資源共享是W3C標(biāo)準(zhǔn))來(lái)實(shí)現(xiàn)POST外驱,PUT請(qǐng)求跨域的。 CORS的詳細(xì)介紹可以參考這里.

通常情況下腻窒,假如服務(wù)器端開啟CORS配置允許任何來(lái)源的請(qǐng)求昵宇,就很難分辨接收到的請(qǐng)求是用戶自主發(fā)送的(往往是和B.com同一個(gè)域下的網(wǎng)頁(yè)),還是攻擊者冒充用戶身份偽造的攻擊請(qǐng)求(往往不同域儿子,例如A.com)瓦哎。

一休哥自制 XSRF 圖示

XSRF防御——Token


經(jīng)過(guò)上面的介紹,其實(shí)防御的辦法大概都可以推斷出來(lái)了柔逼。關(guān)鍵就是區(qū)分來(lái)自于各種域的請(qǐng)求蒋譬,哪些是合法用戶發(fā)送的,哪些是被借用了身份發(fā)送來(lái)的愉适。

  1. 配置服務(wù)器的CORS犯助,只允許白名單的域發(fā)來(lái)請(qǐng)求,這樣最直接维咸。只要白名單的網(wǎng)站不被攻擊注入惡意腳本就基本安全了剂买。以nodejs和express為例,配置如下:
app.all('*', function(req, res, next) {
   // 如果用"*", 表示接受任何域發(fā)來(lái)的請(qǐng)求, 這里只配置一個(gè)域名
   res.header("Access-Control-Allow-Origin", "www.icbc.com");
   res.header("Access-Control-Allow-Headers", "X-Requested-With, accept, origin, content-type");
   res.header("Access-Control-Allow-Methods", "PUT,POST,OPTIONS");
   next();
}

2.bank.com 的服務(wù)器端和客戶端通力合作癌蓖,協(xié)商一個(gè)除了Session之外的二次身份驗(yàn)證——Token瞬哼。

Token驗(yàn)證的原理是:每次用戶登陸成功,就根據(jù)SessionID特定算法生成一個(gè)Token租副,發(fā)回客戶端(動(dòng)態(tài)添加到一個(gè)隱藏域中坐慰,例如<input> 或者JS變量中),合法客戶端在隨后的請(qǐng)求中加入Token作為數(shù)據(jù)體附井,服務(wù)器端每次接受請(qǐng)求都要去驗(yàn)證SessionID 和 Token,雙保險(xiǎn)两残。以nodejs為例永毅,一休哥自制服務(wù)端關(guān)鍵代碼:

// 當(dāng)用戶登錄驗(yàn)證成功時(shí),隨即生成與該用戶Session綁定的Token
req.session.key = (Math.random()* Math.pow(10, 17));
var crsfToken = generateToken(parseInt(req.session.key).toString());
// 返回token給客戶端人弓,客戶端將token動(dòng)態(tài)添加至DOM或者變量中
res.send({"status": returnData, "refreshpage": redirectpage, "token": crsfToken});

// return Hex string as token. 
// 加密算法遠(yuǎn)比這個(gè)復(fù)雜沼死。這里只是演示,這樣也很難猜出token
function generateToken(sess) {
  var tk = "", a = 0.834415, b = 1.214414, c = 1.83121;
  for(var i=0; i < sess.length; i++){
    var baseNum = parseInt(sess[i]);
    tk += (a * Math.pow(baseNum, b) + c).toFixed(0);
  }
  var tkNum = parseInt(tk);
  return tkNum.toString(16);
}

// 當(dāng)收到請(qǐng)求后崔赌,除了驗(yàn)證session意蛀,再根據(jù)session計(jì)算一次token,比對(duì)客戶端發(fā)來(lái)的是否一致健芭。
// check Token to prevent XSRF... 
function checkToken(session, params) {
  var validToken = generateToken(session.name);
  if (params.token && params.token == validToken) {
    return true;
  } else {
    console.error("CSRF Token not valid! Attack Found !!");
    return false;
  }
}

再補(bǔ)充一點(diǎn)县钥,因?yàn)槊俺渖矸莸恼?qǐng)求一般都是趁受害者處于登錄狀態(tài)了,所以DOM中沒(méi)有Token慈迈,而經(jīng)過(guò)合法登錄后才會(huì)有Token存在若贮。這樣就較好地防御了跨站偽造請(qǐng)求攻擊。

寫在最后

現(xiàn)如今,網(wǎng)絡(luò)安全形勢(shì)越來(lái)越嚴(yán)峻谴麦,作為一個(gè)Web前端工程師蠢沿,之前很少注意這一點(diǎn)。至此已經(jīng)更新了兩篇 跟前端工程師相關(guān)的網(wǎng)絡(luò)安全 筆記了匾效。希望大家喜歡本文舷蟀,有所收獲。

傳送門:注意安全第一篇 XSS 跨站腳本注入

另外一篇很棒的英文參考 CSRF Attacks, XSRF or Sea-Surf – What They Are and How to Defend Against Them

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末面哼,一起剝皮案震驚了整個(gè)濱河市野宜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌精绎,老刑警劉巖速缨,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異代乃,居然都是意外死亡旬牲,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門搁吓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)原茅,“玉大人,你說(shuō)我怎么就攤上這事堕仔±揲伲” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵摩骨,是天一觀的道長(zhǎng)通贞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)恼五,這世上最難降的妖魔是什么昌罩? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮灾馒,結(jié)果婚禮上茎用,老公的妹妹穿的比我還像新娘。我一直安慰自己睬罗,他們只是感情好轨功,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著容达,像睡著了一般古涧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上花盐,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天蒿褂,我揣著相機(jī)與錄音圆米,去河邊找鬼。 笑死啄栓,一個(gè)胖子當(dāng)著我的面吹牛娄帖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播昙楚,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼近速,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了堪旧?” 一聲冷哼從身側(cè)響起削葱,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淳梦,沒(méi)想到半個(gè)月后析砸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡爆袍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年首繁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陨囊。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡弦疮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜘醋,到底是詐尸還是另有隱情胁塞,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布压语,位于F島的核電站啸罢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏胎食。R本人自食惡果不足惜扰才,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斥季。 院中可真熱鬧训桶,春花似錦累驮、人聲如沸酣倾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)躁锡。三九已至,卻和暖如春置侍,著一層夾襖步出監(jiān)牢的瞬間映之,已是汗流浹背拦焚。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杠输,地道東北人赎败。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蠢甲,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容