WIKI使用導(dǎo)航
站長百科導(dǎo)航
站長專題
- 網(wǎng)站推廣
- 網(wǎng)站程序
- 網(wǎng)站賺錢
- 虛擬主機
- cPanel
- 網(wǎng)址導(dǎo)航專題
- 云計算
- 微博營銷
- 虛擬主機管理系統(tǒng)
- 開放平臺
- WIKI程序與應(yīng)用
- 美國十大主機
CSRF
CSRF(Cross-site request forgery跨站請求偽造,也被稱成為“one click attack”或者session riding,通??s寫為CSRF或者XSRF,是一種對網(wǎng)站的惡意利用。盡管聽起來像跨站腳本(XSS),但它與XSS非常不同,并且攻擊方式幾乎相左。XSS利用站點內(nèi)的信任用戶,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網(wǎng)站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進(jìn)行防范的資源也相當(dāng)稀少)和難以防范,所以被認(rèn)為比XSS更具危險性。網(wǎng)站是通過cookie來識別用戶的,當(dāng)用戶成功進(jìn)行身份驗證之后瀏覽器就會得到一個標(biāo)識其身份的cookie,只要不關(guān)閉瀏覽器或者退出登錄,以后訪問這個網(wǎng)站會帶上這個cookie。如果這期間瀏覽器被人控制著請求了這個網(wǎng)站的url,可能就會執(zhí)行一些用戶不想做的功能(比如修改個人資料)。因為這個不是用戶真正想發(fā)出的請求,這就是所謂的請求偽造;呵呵,因為這些請求也是可以從第三方網(wǎng)站提交的,所以前綴跨站二字。
CSRF特點[ ]
攻擊通過在授權(quán)用戶訪問的頁面中包含鏈接或者腳本的方式工作。例如:一個網(wǎng)站用戶Bob可能正在瀏覽聊天論壇,而同時另一個用戶Alice也在此論壇中,并且后者剛剛發(fā)布了一個具有Bob銀行鏈接的圖片消息。設(shè)想一下,Alice編寫了一個在Bob的銀行站點上進(jìn)行取款的form提交的鏈接,并將此鏈接作為圖片tag。如果Bob的銀行在cookie中保存他的授權(quán)信息,并且此cookie沒有過期,那么當(dāng)Bob的瀏覽器嘗試裝載圖片時將提交這個取款form和他的cookie,這樣在沒經(jīng)Bob同意的情況下便授權(quán)了這次事務(wù)。CSRF是一種依賴web瀏覽器的、被混淆過的代理人攻擊(deputy attack)。在上面銀行示例中的代理人是Bob的web瀏覽器,它被混淆后誤將Bob的授權(quán)直接交給了Alice使用。下面是CSRF的常見特性:依靠用戶標(biāo)識危害網(wǎng)站、利用網(wǎng)站對用戶標(biāo)識的信任欺騙用戶的瀏覽器發(fā)送HTTP請求給目標(biāo)站點,另外可以通過IMG標(biāo)簽會觸發(fā)一個GET請求,可以利用它來實現(xiàn)CSRF攻擊。
CSRF防御措施[ ]
對于web站點,將持久化的授權(quán)方法(例如cookie或者HTTP授權(quán))切換為瞬時的授權(quán)方法(在每個form中提供隱藏field),這將幫助網(wǎng)站防止這些攻擊。一種類似的方式是在form中包含秘密信息、用戶指定的代號作為cookie之外的驗證。另一個可選的方法是“雙提交”cookie。此方法只工作于Ajax請求,但它能夠作為無需改變大量form的全局修正方法。如果某個授權(quán)的cookie在form post之前正被JavaScript代碼讀取,那么限制跨域規(guī)則將被應(yīng)用。如果服務(wù)器需要在Post請求體或者URL中包含授權(quán)cookie的請求,那么這個請求必須來自于受信任的域,因為其它域是不能從信任域讀取cookie的。與通常的信任想法相反,使用Post代替Get方法并不能提供卓有成效的保護(hù)。因為JavaScript能使用偽造的POST請求。盡管如此,那些導(dǎo)致對安全產(chǎn)生“副作用”的請求應(yīng)該總使用Post方式發(fā)送。Post方式不會在web服務(wù)器和代理服務(wù)器日志中留下數(shù)據(jù)尾巴,然而Get方式卻會留下數(shù)據(jù)尾巴。盡管CSRF是web應(yīng)用的基本問題,而不是用戶的問題,但用戶能夠在缺乏安全設(shè)計的網(wǎng)站上保護(hù)他們的帳戶:通過在瀏覽其它站點前登出站點或者在瀏覽器會話結(jié)束后清理瀏覽器的cookie。 在Web應(yīng)用程序側(cè)防御CSRF漏洞,一般都是利用referer、token或者驗證碼,Nexus的文章已經(jīng)寫的很全面了;superhei也有提出bypass的思路,還有一個思路是在客戶端防御,貌似可以做成一個類似HTTP Watch的軟件,掛在瀏覽器上攔截或者過濾跨域的cookie。 服務(wù)端的CSRF方式方法很多樣,但總的思想都是一致的,就是在客戶端頁面增加偽隨機數(shù)。
- Cookie Hashing(所有表單都包含同一個偽隨機值):這可能是最簡單的解決方案了,因為攻擊者不能獲得第三方的Cookie(理論上),所以表單中的數(shù)據(jù)也就構(gòu)造失敗了:>
<?php //構(gòu)造加密的Cookie信息 $value = “DefenseSCRF”; setcookie(”cookie”, $value, time()+3600); ?>
- 在表單里增加Hash值,以認(rèn)證這確實是用戶發(fā)送的請求。
<?php $hash = md5($_COOKIE['cookie']); ?> <form method=”POST” action=”transfer.php”> <input type=”text” name=”toBankId”> <input type=”text” name=”money”> <input type=”hidden” name=”hash” value=”<?=$hash;?>”> <input type=”submit” name=”submit” value=”Submit”> </form>
- 然后在服務(wù)器端進(jìn)行Hash值驗證
<?php if(isset($_POST['check'])) { $hash = md5($_COOKIE['cookie']); if($_POST['check'] == $hash) { doJob(); } else { //... } } else { //... } ?>
這個方法個人覺得已經(jīng)可以杜絕99%的CSRF攻擊了,那還有1%呢....由于用戶的Cookie很容易由于網(wǎng)站的XSS漏洞而被盜取,這就另外的1%。一般的攻擊者看到有需要算Hash值,基本都會放棄了,某些除外,所以如果需要100%的杜絕,這個不是最好的方法。
- 驗證碼
這個方案的思路是:每次的用戶提交都需要用戶在表單中填寫一個圖片上的隨機字符串,厄....這個方案可以完全解決CSRF,但個人覺得在易用性方面似乎不是太好,還有聽聞是驗證碼圖片的使用涉及了一個被稱為MHTML的Bug,可能在某些版本的微軟IE中受影響。
- One-Time Tokens(不同的表單包含一個不同的偽隨機值)
在實現(xiàn)One-Time Tokens時,需要注意一點:就是“并行會話的兼容”。如果用戶在一個站點上同時打開了兩個不同的表單,CSRF保護(hù)措施不應(yīng)該影響到他對任何表單的提交??紤]一下如果每次表單被裝入時站點生成一個偽隨機值來覆蓋以前的偽隨機值將會發(fā)生什么情況:用戶只能成功地提交他最后打開的表單,因為所有其他的表單都含有非法的偽隨機值。必須小心操作以確保CSRF保護(hù)措施不會影響選項卡式的瀏覽或者利用多個瀏覽器窗口瀏覽一個站點。 以下實現(xiàn):
- 先是令牌生成函數(shù)(gen_token()):
<?php function gen_token() { //這里我是貪方便,實際上單使用Rand()得出的隨機數(shù)作為令牌,也是不安全的。 //這個可以參考我寫的Findbugs筆記中的《Random object created and used only once》 $token = md5(uniqid(rand(), true)); return $token; }
- 然后是Session令牌生成函數(shù)(gen_stoken()):
<?php function gen_stoken() { $pToken = ""; if($_SESSION[STOKEN_NAME] == $pToken){ //沒有值,賦新值 $_SESSION[STOKEN_NAME] = gen_token(); } else{ //繼續(xù)使用舊的值 } } ?>
- WEB表單生成隱藏輸入域的函數(shù):
<?php function gen_input() { gen_stoken(); echo “<input type=\”hidden\” name=\”" . FTOKEN_NAME . “\” value=\”" . $_SESSION[STOKEN_NAME] . “\”> “; } ?>
- WEB表單結(jié)構(gòu):
<?php session_start(); include(”functions.php”); ?> <form method=”POST” action=”transfer.php”> <input type=”text” name=”toBankId”> <input type=”text” name=”money”> <? gen_input(); ?> <input type=”submit” name=”submit” value=”Submit”> </FORM>
- 服務(wù)端核對令牌:
檢測CSRF[ ]
檢測CSRF漏洞都是體力活了,先抓取一個正常請求的數(shù)據(jù)包,然后去掉referer字段再重新提交,如果還是有效那基本上就存在問題了。當(dāng)然參數(shù)可能含有不能預(yù)測的參數(shù)(比如userid什么的),這個時候就看這個不可預(yù)測的參數(shù)能不能通過其他手段比如flash拿到,如果能,呵呵,則還是存在問題。還有就是試著改post為get,因為有些程序是不區(qū)分get/post的。應(yīng)用程序的功能和返回形式都各不相同,所以想自動化測試CSRF漏洞還是有點困難的,OWASP上面有一個叫做CSRFTester的工具不妨拿來一試