CSRF站外類型的漏洞其實就是傳統意義上的外部提交數據問題,一般程序員會考慮給一些留言評論等的表單加上水印以防止SPAM問題,但是為了用戶的體驗性,一些操作可能沒有做任何限制,所以攻擊者可以先預測好請求的參數,在站外的Web頁面里編寫javascript腳本偽造文件請求或和自動提交的表單來實現GET、POST請求,用戶在會話狀態下點擊鏈接訪問站外的Web頁面,客戶端就被強迫發起請求.
瀏覽器的安全缺陷
現在的Web應用程序幾乎都是使用Cookie來識別用戶身份以及保存會話狀態,但是所有的瀏覽器在最初加入Cookie功能時并沒有考慮安全因素,從 WEB頁面產生的文件請求都會帶上COOKIE,如下所示,Web頁面中的一個正常的圖片所產生的請求也會帶上COOKIE:
<img src=”http://website/logo.jpg”>
GET http://website.com/log.jpg
Cookie:session_id,客戶端,服務器,咱們按照這個思路,山寨一個crumb的實現,代碼如下:
- class Crumb {
- CONST SALT = "your-secret-salt";
- static $ttl = 7200;
- static public function challenge($data) {
- return hash_hmac('md5', $data, self::SALT);
- }
- //開源代碼Vevb.com
- static public function issueCrumb($uid, $action = -1) {
- $i = ceil(time() / self::$ttl);
- return substr(self::challenge($i . $action . $uid), -12, 10);
- }
- static public function verifyCrumb($uid, $crumb, $action = -1) {
- $i = ceil(time() / self::$ttl);
- if(substr(self::challenge($i . $action . $uid), -12, 10) == $crumb ||
- substr(self::challenge(($i - 1) . $action . $uid), -12, 10) == $crumb)
- return true;
- return false;
- }
- }
代碼中的$uid表示用戶唯一標識,而$ttl表示這個隨機串的有效時間.
應用示例,在表單中插入一個隱藏的隨機串crumb,代碼如下:
- <form method="post" action="demo.php">
- <input type="hidden" name="crumb" value="<?php echo Crumb::issueCrumb($uid)?>">
- <input type="text" name="content">
- <input type="submit">
- </form>
處理表單 demo.php,對crumb進行檢查,代碼如下:
- if(Crumb::verifyCrumb($uid, $_POST['crumb'])) {
- //按照正常流程處理表單
- } else {
- //crumb校驗失敗,錯誤提示流程
- }
注意:CSRF攻擊和相關web蠕蟲的爆發,并且針對這類web攻擊制定有效的應急措施,同建議程序員不要濫用$_REQUEST類變量,在必要的情況下給某些敏感的操作加上水印,考慮使用類似DISCUZ論壇的formhash技術提高黑客預測請求參數的難度,注意JSON數據接口的安全問題等.
新聞熱點
疑難解答