王應(yīng)軍,傅建明,姜百合
(武漢大學(xué) 計(jì)算機(jī)學(xué)院,武漢 430072)
跨站請(qǐng)求偽造(Cross-site Request Forgery,CSRF)攻擊就是攻擊者通過(guò)一些技術(shù)手段欺騙用戶的瀏覽器去訪問(wèn)一個(gè)自己曾經(jīng)認(rèn)證過(guò)的網(wǎng)站并執(zhí)行一些操作(如發(fā)郵件、發(fā)消息、加好友、甚至是財(cái)產(chǎn)操作)。由于瀏覽器曾經(jīng)認(rèn)證過(guò),因此被訪問(wèn)的網(wǎng)站會(huì)認(rèn)為是真正用戶的操作而去執(zhí)行,實(shí)際上是執(zhí)行攻擊者構(gòu)造的操作。
隨著互聯(lián)網(wǎng)、云計(jì)算、移動(dòng)計(jì)算的高速發(fā)展,網(wǎng)站提供的功能越來(lái)越豐富,用戶能夠進(jìn)行的操作也越來(lái)越多,從而也存在更多潛在的CSRF攻擊。根據(jù)OWASP[1]發(fā)布的Web應(yīng)用十大安全隱患報(bào)告,CSRF排名前八位。2007年,谷歌Gmail遭受了嚴(yán)重的CSRF攻擊[2],攻擊者通過(guò)在惡意網(wǎng)站上偽造對(duì)受害者Gmail中郵件的轉(zhuǎn)發(fā)請(qǐng)求鏈接,使得成千上萬(wàn)用戶的郵件遭到泄露。新浪某社區(qū)因存在CSRF漏洞,誘騙用戶點(diǎn)擊可造成蠕蟲[3]。Facebook和Dropbox在聯(lián)合使用過(guò)程中,因?yàn)閍uth使用不當(dāng),導(dǎo)致利用CSRF攻擊可以上傳任意文件到Facebook[4]。據(jù)不完全統(tǒng)計(jì),截止2016年5月,在烏云漏洞平臺(tái)[5]上提交的CSRF漏洞數(shù)累計(jì)有330多個(gè),說(shuō)明CSRF漏洞廣泛存在。
目前主流防御CSRF的思路包括驗(yàn)證請(qǐng)求來(lái)源與防止請(qǐng)求重放。驗(yàn)證請(qǐng)求來(lái)源如驗(yàn)證用戶提交請(qǐng)求的referer,但referer是由客戶端發(fā)送可以被偽造從而產(chǎn)生漏報(bào)。防止請(qǐng)求重放的常見方法包括在Form表單中增加Token或者在執(zhí)行敏感操作時(shí)需要用戶輸入驗(yàn)證碼,但要求用戶輸入驗(yàn)證碼時(shí)會(huì)影響用戶體驗(yàn)?;赥oken的防御方法也能夠利用postMessage、JSONP的方法,獲取Token進(jìn)而執(zhí)行CSRF攻擊[6]。以上的防御方法存在著用戶體驗(yàn)差、兼容性差、防御方法易被繞過(guò)、Token泄漏導(dǎo)致CSRF攻擊等多種問(wèn)題,不能在實(shí)際應(yīng)用中有效地防御CSRF攻擊。
為此,本文提出一種基于URL地址請(qǐng)求參數(shù)名隨機(jī)化的CSRF防御方案。通過(guò)對(duì)請(qǐng)求參數(shù)名進(jìn)行隨機(jī)化,使其不可預(yù)測(cè)從而使攻擊者無(wú)法進(jìn)行重放。服務(wù)端接受瀏覽器請(qǐng)求后對(duì)請(qǐng)求參數(shù)名進(jìn)行驗(yàn)證來(lái)判斷請(qǐng)求是否合法。隨機(jī)化的密鑰在每次建立會(huì)話時(shí)產(chǎn)生,攻擊者無(wú)法預(yù)知。被隨機(jī)化的參數(shù)也是在服務(wù)器端隨機(jī)化之后發(fā)送到瀏覽器,攻擊者無(wú)法獲知隨機(jī)化的請(qǐng)求參數(shù)名。所以,基于參數(shù)名的隨機(jī)化的CSRF防御方案本身不會(huì)泄露隨機(jī)化參數(shù)的信息,同時(shí)隨機(jī)化的操作是在服務(wù)器端完成,在保障用戶體驗(yàn)的同時(shí)防御CSRF攻擊。
CSRF防御方法根據(jù)CSRF檢測(cè)位置的不同可以分為服務(wù)端防御、客戶端防御??蛻舳朔烙鶄?cè)重于跨域請(qǐng)求的審查;服務(wù)端防御側(cè)重于防止請(qǐng)求重放。
服務(wù)端常用的防御方法就是采用基于驗(yàn)證碼的防御方法、基于referer的驗(yàn)證防御方法與Token的防御方法。
基于驗(yàn)證碼的防御方案是在關(guān)鍵位置要求用戶輸入驗(yàn)證碼。但是由于輸入驗(yàn)證碼的用戶體驗(yàn)較差,目前這種方案沒有廣泛使用?;趓eferer的防御思路是服務(wù)器端驗(yàn)證請(qǐng)求的referer。但是由于用戶的隱私設(shè)置或者是網(wǎng)絡(luò)傳輸?shù)膯?wèn)題,服務(wù)器最終不一定能得到referer,因此基于referer的防御方法存在漏報(bào)、誤報(bào)的問(wèn)題,也沒有被廣泛采用。
基于Token的防御方法[7]的思路是在需要進(jìn)行敏感、重要操作時(shí),在對(duì)應(yīng)的Form表單的地方添加Token,Token一般是一個(gè)隨機(jī)數(shù)。當(dāng)用戶通過(guò)表單提交請(qǐng)求時(shí),這個(gè)Token也會(huì)一并提交上去。在正常訪問(wèn)時(shí),客戶端瀏覽器能夠正確得到這個(gè)Token。但是在CSRF攻擊中,攻擊者無(wú)法事先知道這個(gè)Token,從而能夠防御CSRF攻擊。目前這種防御方法,如Django、Ruby on Rails、ThinkPHP被廣泛地采用。但是這種防御方法也存在缺陷:1)如果對(duì)Cookie處理不當(dāng),則導(dǎo)致CSRF的防御方法可以被繞過(guò)[8];2)Web應(yīng)用與第三方進(jìn)行跨域交互時(shí)可能會(huì)泄露Token,如利用JSONP、postMessage可以獲取到Token[9]。
客戶端的防御方法一般都是在瀏覽器端識(shí)別出CSRF攻擊,阻斷CSRF的請(qǐng)求或者剝離所有的認(rèn)證信息。鑒于服務(wù)器的防護(hù)方法需要修改服務(wù)器端的代碼,很多的學(xué)者都是研究基于客戶端的防御方法。CsFire[10]是一款基于Firefox的插件,CSFire對(duì)跨域的2個(gè)網(wǎng)站的相關(guān)性進(jìn)行判斷以此界定是否為CSRF攻擊。CsFire如果發(fā)現(xiàn)跨域的2個(gè)網(wǎng)站之前存在交互,則認(rèn)為此請(qǐng)求合法,否則認(rèn)為是CSRF攻擊。但是此工具在面對(duì)Flicker、Yahoo等第三方登錄的情形時(shí)會(huì)存在很大的誤報(bào)。BEAP[11]則是通過(guò)判斷當(dāng)前用戶發(fā)起的請(qǐng)求是否是基于用戶意圖以此來(lái)防御CSRF攻擊的一款瀏覽器插件。BEAP通過(guò)監(jiān)控用戶網(wǎng)頁(yè)行為以此判斷當(dāng)前點(diǎn)擊是否是基于用戶的意圖點(diǎn)擊。例如如果用戶在地址欄輸入U(xiǎn)RL地址,則認(rèn)為是基于用戶的本意訪問(wèn);如果用戶點(diǎn)擊郵件中的鏈接,則認(rèn)為是CSRF攻擊,從而阻止該請(qǐng)求。BEAP這種方式存在很大的誤報(bào),目前很多網(wǎng)站注冊(cè)都需要用戶點(diǎn)擊郵件中的注冊(cè)鏈接進(jìn)行確認(rèn),BEAP對(duì)這類行為都會(huì)產(chǎn)生誤報(bào)。文獻(xiàn)[12]提出的同源信用應(yīng)用協(xié)議以Web站點(diǎn)的信用度為指標(biāo),計(jì)算訪問(wèn)請(qǐng)求地址的信用來(lái)決定該地址是否可達(dá),防止從跨域名網(wǎng)站引入惡意資源。但是該方法還是通過(guò)插件的方式加以實(shí)現(xiàn)的,導(dǎo)致協(xié)議還是可以被攻擊者破解從而繞過(guò)。
從研究者們的研究成果以及實(shí)際應(yīng)用可以看出,基于客戶端的防御存在兼容性、用戶體驗(yàn)差、漏報(bào)、誤報(bào)以及易被繞過(guò)等不同程度的問(wèn)題?;诜?wù)器端的防御才能夠有效地防御CSRF攻擊,但是基于referer的防御方法由于referer容易被偽造從而繞過(guò)檢測(cè)。驗(yàn)證碼雖然能夠有效地防御CSRF攻擊,但是用戶體驗(yàn)差。所以,目前最常用的防御方法是基于Token的防御方法,但是Token也存在著Token泄露的問(wèn)題。
本文提出基于隨機(jī)化的參數(shù)名跨站請(qǐng)求偽造的防御方法,將攻擊者可偽造的請(qǐng)求參數(shù)名作為隨機(jī)化對(duì)象,使其具有隨機(jī)性和不可預(yù)測(cè)性,以此防御CSRF攻擊。隨機(jī)化技術(shù)是一種新型的保護(hù)系統(tǒng)免受攻擊的通用方法,可以有效地打破同構(gòu)和穩(wěn)定性的環(huán)境,以異構(gòu)和隨機(jī)的環(huán)境來(lái)應(yīng)對(duì)未知的攻擊。
目前也有很多的學(xué)者研究如何將隨機(jī)化的技術(shù)應(yīng)用在Web安全防御中。文獻(xiàn)[13-14]均提出通過(guò)指令集隨機(jī)化的方法防御SQL 注入攻擊,其主要思想就是對(duì)SQL語(yǔ)句中的關(guān)鍵字后添加隨機(jī)數(shù),之后對(duì)組裝的SQL語(yǔ)句進(jìn)行驗(yàn)證。但是由于實(shí)現(xiàn)難度較高,最后采用的是通過(guò)代理服務(wù)器的方式實(shí)現(xiàn)的。由于代理服務(wù)器需要對(duì)HTML解析和分析,因此這種方式的兼容性、開銷都存在問(wèn)題。文獻(xiàn)[15]提出基于指令隨機(jī)化的XSS的檢測(cè)方法,通過(guò)HTML/JavaScript關(guān)鍵字會(huì)在末尾追加隨機(jī)生成的字符串,攻擊者無(wú)法預(yù)測(cè),由于這種方式實(shí)現(xiàn)復(fù)雜同樣采用的是代理的方式,因此也會(huì)存在兼容性差、開銷大的問(wèn)題。文獻(xiàn)[16]提出網(wǎng)頁(yè)標(biāo)記隨機(jī)化對(duì)抗XSS 攻擊,鑒于通過(guò)代理的方式實(shí)現(xiàn)隨機(jī)化的效果較差,該方法主要是在PHP平臺(tái)上實(shí)現(xiàn)。在服務(wù)器通過(guò)修改Smarty的代碼來(lái)對(duì)HTML的標(biāo)簽進(jìn)行標(biāo)記,在客戶端通過(guò)代理的方式對(duì)標(biāo)記的標(biāo)簽進(jìn)行驗(yàn)證,雖然具有很好的效果,但是僅適用于使用了Smarty的PHP代碼。
鑒于目前隨機(jī)化的方法在Web安全方面開始逐步應(yīng)用,但是針對(duì)CSRF的防御卻并沒有使用隨機(jī)化的方法,同時(shí)之前研究者們提出的針對(duì)CSRF的防御方法均存在不同程度的問(wèn)題,本文提出了基于參數(shù)名的隨機(jī)化防御方法,不同于通過(guò)代理的方式進(jìn)行隨機(jī)化和去隨機(jī)化,本文主要是基于源代碼的分析,提供一種通用的CSRF防御思路并且在PHP開源程序上加以驗(yàn)證。
本節(jié)首先分析CSRF攻擊的原理,然后提出一種基于請(qǐng)求參數(shù)名隨機(jī)化的CSRF防御方法,最后說(shuō)明基于隨機(jī)化防御方法的PHP代碼的實(shí)現(xiàn)。
CSRF利用網(wǎng)站對(duì)用戶網(wǎng)頁(yè)瀏覽器的信任,欺騙用戶的瀏覽器去執(zhí)行非本意的操作。CSRF攻擊的原理如圖1所示。
圖1 CSRF攻擊原理
當(dāng)網(wǎng)站A收到了用戶瀏覽器發(fā)送的轉(zhuǎn)賬請(qǐng)求R時(shí),由于瀏覽器攜帶了用戶的Cookie,網(wǎng)站A認(rèn)為請(qǐng)求R是由用戶發(fā)送的就會(huì)按照用戶的權(quán)限處理步驟5的請(qǐng)求,這樣網(wǎng)站B就達(dá)到了模擬用戶操作的目的,成功地實(shí)施CSRF攻擊。CSRF能夠成功實(shí)施的一個(gè)重要的原因是在于所有的用戶在登錄網(wǎng)站A時(shí)看到的網(wǎng)頁(yè)結(jié)構(gòu)與參數(shù)名都是一樣的,攻擊者很容易構(gòu)造出一個(gè)與普通用戶一樣的操作的請(qǐng)求。
目前主要的HTTP請(qǐng)求方法是GET和POST。從數(shù)據(jù)表現(xiàn)形式上來(lái)看,GET請(qǐng)求方法的請(qǐng)求數(shù)據(jù)顯式地嵌入在URL中;而POST請(qǐng)求方法的請(qǐng)求數(shù)據(jù)隱式地嵌入在HTML表單中,提交表單時(shí)用戶無(wú)法看到提交的內(nèi)容。但是無(wú)論是通過(guò)什么方式提交數(shù)據(jù),提交的字段名對(duì)于所有的用戶都是不變的。對(duì)于用戶來(lái)說(shuō),假設(shè)轉(zhuǎn)賬請(qǐng)求的字段名為fromaccount、toaccount、money。攻擊者看到轉(zhuǎn)賬請(qǐng)求的字段名同樣是fromaccount、toaccount、money。這種靜態(tài)的可預(yù)測(cè)的參數(shù)名,使得所有的用戶發(fā)送請(qǐng)求時(shí)的參數(shù)名都一樣,因而攻擊者能夠偽造出“合法”的惡意請(qǐng)求實(shí)施CSRF攻擊。這種CSRF攻擊方法本質(zhì)上就是一種重放攻擊。
根據(jù)2.1節(jié)中對(duì)CSRF攻擊原理的分析發(fā)現(xiàn),阻止請(qǐng)求重放就能夠有效地防御CSRF攻擊。通過(guò)Token的方式來(lái)防御CSRF的防御方法利用的就是阻止攻擊者重放的思想。本文提出的基于請(qǐng)求參數(shù)名隨機(jī)化的防御方法,將傳統(tǒng)的靜態(tài)可預(yù)測(cè)的請(qǐng)求參數(shù)名作為隨機(jī)化為不可預(yù)測(cè)的字符串以防御CSRF攻擊,本質(zhì)上也是一種阻止攻擊者請(qǐng)求重放的方法,但是比Token方法能夠更有效地防御CSRF攻擊。
在隨機(jī)化算法的選擇方面,考慮到需要對(duì)參數(shù)進(jìn)行加密和解密,還要保證在用戶訪問(wèn)的時(shí)候參數(shù)名稱不同,綜合考慮采用的是對(duì)稱性加密算法,將加密密鑰保存在SESSION中。為了保證用戶在每次與網(wǎng)站建立會(huì)話時(shí)的加密密鑰都是不同的,密鑰的生成及用戶與服務(wù)建立會(huì)話的時(shí)間相關(guān),同時(shí)采用摘要算法生成密鑰。這樣就保證了同一用戶在不同時(shí)刻以及不同用戶在同一時(shí)刻訪問(wèn)網(wǎng)站所得到的網(wǎng)站的參數(shù)名都是不同的,攻擊者無(wú)法猜測(cè)到用戶的隨機(jī)化的參數(shù)名,也無(wú)法獲知密鑰,保證了CSRF攻擊難以實(shí)施。整個(gè)隨機(jī)化防御原理如圖2所示。
當(dāng)用戶向服務(wù)器發(fā)送請(qǐng)求之后,服務(wù)端如果判斷用戶不是第一次訪問(wèn),則直接返回已經(jīng)隨機(jī)化后的頁(yè)面。如果用戶是第一次訪問(wèn),則創(chuàng)建隨機(jī)化密鑰,同時(shí)對(duì)訪問(wèn)頁(yè)面中的參數(shù)進(jìn)行隨機(jī)化處理,返回隨機(jī)化之后的頁(yè)面給用戶。用戶在頁(yè)面中填寫完畢發(fā)送至服務(wù)器之后,服務(wù)器對(duì)隨機(jī)化的參數(shù)進(jìn)行還原。如果服務(wù)器能夠還原成為原來(lái)的參數(shù),則正常響應(yīng)用戶的請(qǐng)求;否則,服務(wù)器判定為CSRF攻擊,拒絕響應(yīng)。
為了方便開發(fā)者部署本文的方案,本文實(shí)現(xiàn)一個(gè)PHP的第三方庫(kù)CSRFP[17],用于實(shí)現(xiàn)生成隨機(jī)化密鑰、參數(shù)名隨機(jī)化以及對(duì)已經(jīng)隨機(jī)化的參數(shù)名還原。通過(guò)對(duì)國(guó)內(nèi)外常見的PHP開源程序(wordpress、joomla、drupal、discuz、phpcms、dedecms、74cms)的分析,發(fā)現(xiàn)這些程序都會(huì)引入公共文件,如config.php、common.php、functions.php等。這些文件一般都是集合了程序常使用的功能,如格式化字符串、頁(yè)面輸出,同時(shí)也用于對(duì)GET、POST參數(shù)過(guò)濾,以防止XSS、SQL注入攻擊。在這些公共文件中引入CSFRP庫(kù)就可以在整個(gè)程序中對(duì)參數(shù)進(jìn)行隨機(jī)化和對(duì)隨機(jī)化的參數(shù)名還原。開發(fā)者可以自行選擇需要進(jìn)行隨機(jī)化防御的位置。開發(fā)者通過(guò)引入CSRFP庫(kù),不需要修改原來(lái)程序的邏輯和代碼就能夠很容易實(shí)現(xiàn)對(duì)網(wǎng)站的加固。
考慮到目前CSRF攻擊主要是POST型的攻擊。所以,在實(shí)驗(yàn)過(guò)程中只對(duì)表單中的參數(shù)名進(jìn)行隨機(jī)化。
對(duì)參數(shù)名進(jìn)行隨機(jī)化的示例代碼如下:
name="">
通過(guò)在公共文件類似common.php中引入CSRFP庫(kù),就能夠完成對(duì)隨機(jī)化的參數(shù)名進(jìn)行還原,代碼如下:
foreach ($_POST as $random_name=> $value) {
$name=CSRFP::decrypt($random_name);
$_POST[$name]=$_POST[$random_name];}
通過(guò)解密還原的代碼可以看出,主要就是對(duì)$_POST中的已經(jīng)隨機(jī)化的random_name進(jìn)行解密還原為name。如果隨機(jī)化的random_name是被攻擊者篡改或者是由攻擊者創(chuàng)建的,那么在進(jìn)行解密為name時(shí)無(wú)法正確還原,之后的處理流程就會(huì)失敗,從而丟棄這次請(qǐng)求,保護(hù)網(wǎng)站不會(huì)受到CSRF攻擊。CSRF隨機(jī)化防御流程如圖3所示。
圖3 隨機(jī)化防御流程
對(duì)比2.1節(jié)CSRF的攻擊原理,當(dāng)使用了隨機(jī)化參數(shù)名的CSRF防御方法之后,參數(shù)名稱完全是隨機(jī)的字符串(步驟2)。當(dāng)攻擊者發(fā)起CSRF攻擊時(shí),攻擊者無(wú)法知道新的參數(shù)名而是按照之前的參數(shù)名發(fā)起攻擊(步驟4)。當(dāng)服務(wù)器端收到這些參數(shù)名進(jìn)行校驗(yàn)時(shí),檢驗(yàn)失敗,從而判定為不是正常請(qǐng)求,拒絕響應(yīng)(步驟5和步驟6)。通過(guò)這種方法可以有效地防御CSRF攻擊。
本節(jié)對(duì)基于隨機(jī)化參數(shù)名CSRF防御方法的有效性和性能進(jìn)行測(cè)試以及安全性分析,同時(shí)與目前主流的基于Token的CSRF防御方法進(jìn)行對(duì)比分析。實(shí)驗(yàn)分析方法是通過(guò)在本地搭建Apache、MySQL、PHP的網(wǎng)站運(yùn)行環(huán)境,應(yīng)用隨機(jī)化的防御方案加固存在CSRF漏洞的PHP開源程序,檢測(cè)有效性;通過(guò)記錄應(yīng)用隨機(jī)化的防御方案之后的訪問(wèn)時(shí)間來(lái)分析性能。
在有效性方面,實(shí)驗(yàn)選取了國(guó)內(nèi)外存在CSRF漏洞的開源PHP程序進(jìn)行部署和實(shí)驗(yàn)分析。根據(jù)Czeskis[18]所進(jìn)行的實(shí)驗(yàn)方法,選取國(guó)外的PHP開源程序是Selectapix、UseBB、PHPDug、PoMMo。國(guó)內(nèi)的PHP開源程序選擇的是PHPCMS、EmpireCMS、FineCMS和蟬知CMS。所選取的PHP開源程序都存在CSRF漏洞。同時(shí)還與目前主流的CSRF防御方法——基于Token的防御方法進(jìn)行了對(duì)比實(shí)驗(yàn)。實(shí)驗(yàn)結(jié)果如表1所示,其中,√為可以被防御,—為無(wú)法防御。
表1 隨機(jī)化防御實(shí)驗(yàn)結(jié)果
從實(shí)驗(yàn)結(jié)果可以發(fā)現(xiàn),采用基于隨機(jī)化的防御方法比基于Token的防御方法更有效。例如PHPCMS的CSRF攻擊使用Token無(wú)法防御,但是使用基于隨機(jī)化的方法可以被防御。PHPCMS的CSRF漏洞出現(xiàn)添加友情鏈接的地方,默認(rèn)情況下會(huì)在添加鏈接后面加上Token,第三方鏈接就能夠得到Token,造成了Token的泄露。當(dāng)管理員審核此鏈接時(shí),就會(huì)執(zhí)行CSRF攻擊。
如果采用隨機(jī)化的防御方法,不會(huì)在任何地方添加Token,那么就不存在泄露的問(wèn)題,所以,能夠防御CSRF攻擊。而FineCMS的CSRF攻擊,2種防御方法均無(wú)法防御,原因在于FineCMS是通過(guò)XSS的方法得到了Token,從而執(zhí)行CSRF攻擊。無(wú)論是采用Token還是隨機(jī)化的防御方法,都可以通過(guò)XSS的方法得到相關(guān)參數(shù)名和參數(shù)值,所以無(wú)法防御。
綜合實(shí)驗(yàn)結(jié)果可以看出,基于參數(shù)名的隨機(jī)化方案比基于Token的防御方法能夠更加有效地防御CSRF攻擊。
在隨機(jī)化的方法中,需要生成隨機(jī)化密鑰并對(duì)參數(shù)進(jìn)行加密。所以,性能測(cè)試包括不同的對(duì)稱性加密算法與不同摘要算法的性能差異、基于Token的防御方法的性能差異、隨機(jī)化的input數(shù)量對(duì)性能的影響。
實(shí)驗(yàn)方法是用PHP編寫一個(gè)常見的用戶注冊(cè)頁(yè)面,此頁(yè)面中包含了一個(gè)注冊(cè)的Form表單,通過(guò)增加Form表單中的input數(shù)量來(lái)測(cè)試input數(shù)量對(duì)防御方法的性能的影響。性能測(cè)試的方法采用的是文獻(xiàn)[19]的分析方法,性能測(cè)試的數(shù)據(jù)是基于頁(yè)面所加載的時(shí)間,頁(yè)面加載的時(shí)間是以Chrome Dev Tools Load的時(shí)間作為訪問(wèn)時(shí)間,連續(xù)訪問(wèn)10次獲取平均值作為最終的訪問(wèn)時(shí)間。圖4是性能測(cè)試的實(shí)驗(yàn)結(jié)果。
圖4 隨機(jī)化防御性能測(cè)試結(jié)果
圖4橫坐標(biāo)標(biāo)識(shí)的是Form表單中的input數(shù)量,縱坐標(biāo)標(biāo)識(shí)頁(yè)面加載的時(shí)間,每一條曲線表示不同的摘要算法和對(duì)稱性加密算法組合一起的隨機(jī)化算法。曲線Token表示的是在Form表單中增加一個(gè)隱藏的Token,頁(yè)面曲線表示只有Form表單(以下均稱為頁(yè)面曲線)。
從圖4可以看出,不同的摘要算法和對(duì)稱性算法組合在一起的隨機(jī)化算法之前沒有很大的差別,但是隨著Form表單中的input數(shù)量變多,算法的耗時(shí)增加?;赥oken的防御方法的耗時(shí)保持不變。雖然如此,但是基于隨機(jī)化參數(shù)名防御方法的耗時(shí)與基于Token的防御方法耗時(shí)相差不大,最大差距為15 ms,與頁(yè)面曲線的差距為25 ms,最大差距為40 ms,不影響用戶的體驗(yàn)。在空間消耗方面,基于Token的防御方法和基于隨機(jī)化參數(shù)名的方法的空間消耗是一樣的,對(duì)于每一個(gè)用戶,只需要保存32位的字符串即可。對(duì)于Token來(lái)說(shuō),保存的是Form表單中的Token域的值,對(duì)于基于隨機(jī)化參數(shù)名的方法來(lái)說(shuō),保存的是隨機(jī)化的密鑰,兩者的長(zhǎng)度都是32位。所以,2種方法在空間損耗上面沒有差異性。
在性能損耗方面,可以發(fā)現(xiàn)當(dāng)只有2個(gè)input標(biāo)簽時(shí),基于隨機(jī)化算法的耗時(shí)與基于Token的防御方法耗時(shí)相當(dāng)。所以,當(dāng)Form中的input數(shù)量較多時(shí),開發(fā)者可以有選擇性地只對(duì)其中的幾個(gè)input標(biāo)簽進(jìn)行隨機(jī)化,在保證隨機(jī)化方法的有效性的同時(shí)還可以確保性能開銷較小。
安全性分析主要包括2個(gè)方面,即防御方法本身的安全性以及程序使用了防御方法之后的安全性。
對(duì)于防御方法本身的安全性分析的前提在于,攻擊者只能發(fā)起CSRF攻擊而無(wú)法通過(guò)其他的攻擊方法使隨機(jī)化的防御方法失效,比如通過(guò)SQL注入、文件讀取的方式獲得網(wǎng)站的源代碼從而繞過(guò)CSRF的驗(yàn)證。如果攻擊者需要繞過(guò)防御方法就必須要知道隨機(jī)化密鑰和隨機(jī)化的加密算法。密鑰的生成在每一次用戶與網(wǎng)站建立會(huì)話時(shí)都不一樣,與當(dāng)前服務(wù)器端的時(shí)間相關(guān),所以攻擊者無(wú)法猜解出密鑰的,同時(shí)密鑰是保存在SESSION中的,攻擊者無(wú)法通過(guò)任何的攻擊手段得到SESSION中的值,從而保證了隨機(jī)化密鑰的安全性。至于隨機(jī)化加密算法的安全性,由于加密算法是保存在服務(wù)器端,除非攻擊者能夠得到網(wǎng)站的源代碼,在一般情況下攻擊者是無(wú)法得到源代碼的,因此加密算法也是比較安全的。
本文對(duì)比使用了防御方案前后的請(qǐng)求流程,隨機(jī)化防御分析如圖5所示。
圖5 隨機(jī)化防御分析對(duì)比
在圖5中,虛線標(biāo)識(shí)的是使用隨機(jī)化防御之后在整個(gè)流程中發(fā)生變化的地方,包括頁(yè)面的隨機(jī)化和后臺(tái)的驗(yàn)證操作。其中在客戶端的改變是頁(yè)面中的參數(shù)的變化,由原來(lái)的具有含義的參數(shù)變?yōu)榱藷o(wú)意義的字符串。從前臺(tái)頁(yè)面中分析,對(duì)攻擊者來(lái)說(shuō),頁(yè)面中的參數(shù)名發(fā)生改變,并沒有增加新的輸入和輸出以及功能方面的問(wèn)題,因此雖然參數(shù)名發(fā)生了變化,但是并沒有增加新的攻擊點(diǎn)。后臺(tái)服務(wù)器端程序的改變?cè)谟陔S機(jī)化密鑰的生成和保存、隨機(jī)化參數(shù)名以及參數(shù)驗(yàn)證。密鑰的生成是由算法完成,密鑰的保存是保存在程序中的SESSION,SESSION是保存在服務(wù)器端的鍵值對(duì),密鑰的生成和存儲(chǔ)對(duì)程序的整個(gè)功能不會(huì)有影響。其次是對(duì)Form表單中的參數(shù)進(jìn)行隨機(jī)化,通過(guò)對(duì)參數(shù)名進(jìn)行隨機(jī)化的加密操作,不會(huì)加入新的輸入輸出和新功能,只會(huì)改變頁(yè)面中的參數(shù)名,因此不會(huì)引入新的問(wèn)題。最后是對(duì)參數(shù)名的驗(yàn)證,通過(guò)圖5的流程發(fā)現(xiàn),對(duì)參數(shù)名的檢驗(yàn)是在服務(wù)器處理之前,這種處理方式在目前的Web開發(fā)中十分常見,類似Java中的Filter、PHP中的include common.php。如果驗(yàn)證通過(guò),再由后面后臺(tái)服務(wù)器的程序進(jìn)行處理。所以,對(duì)參數(shù)名的檢驗(yàn)并不會(huì)影響整個(gè)程序的功能,只是多增加了對(duì)參數(shù)名的檢驗(yàn)和過(guò)濾。
因此通過(guò)綜合分析,當(dāng)程序應(yīng)用了隨機(jī)化的防御方案之后,除了在SESSION中保存隨機(jī)化的密鑰,并沒有在程序中引用新的變量、新的輸入和輸出,隨機(jī)化的參數(shù)檢驗(yàn)不會(huì)對(duì)程序的整個(gè)流程造成影響,這種防御部署方式也是目前Web開發(fā)中常用的防御部署方式。
針對(duì)目前流行的CSRF攻擊,本文提出一種參數(shù)名隨機(jī)化CSRF防御方法。該隨機(jī)化方法部署在Web服務(wù)端,開發(fā)者應(yīng)用本文開發(fā)的PHP開源庫(kù),自行選擇需要隨機(jī)化的參數(shù)名,利用請(qǐng)求和響應(yīng)中隨機(jī)化參數(shù)名的一致性識(shí)別偽造請(qǐng)求,從而檢測(cè)CSRF攻擊。與已有基于客戶端的防御方法相比,隨機(jī)化方法的漏報(bào)和誤報(bào)較低。與已有服務(wù)端的Token策略相比,不存在因?yàn)镴SONP和postMessage的方法使得Token泄露而導(dǎo)致CSRF攻擊的情況。實(shí)驗(yàn)結(jié)果表明,CSRF隨機(jī)化防御方案比基于Token的方法能夠更加有效地防御CSRF攻擊,同時(shí)不影響用戶體驗(yàn)。隨著其不斷應(yīng)用,該方案會(huì)得到不斷的完善。
為了能夠更加方便地應(yīng)用基于參數(shù)名隨機(jī)化CSRF的防御方法,下一步在Web服務(wù)器如apache、nginx上以插件的形式進(jìn)行參數(shù)名隨機(jī)化,以在不修改程序代碼的情況下完成參數(shù)名隨機(jī)化的防護(hù)工作,同時(shí)解決性能開銷的問(wèn)題。