XSS,CSRF,Cookie防劫持的處理
Cookie與session
HTTP天然是無狀態的協議, 為了維持和跟蹤用戶的狀態, 引入了Cookie和Session. Cookie包含了瀏覽器客戶端的用戶憑證, 相對較小. Session則維護在服務器, 用於維護相對較大的用戶信息.
用通俗的語言, Cookie是鑰匙, Session是鎖芯.
Cookie簡單理解就是鑰匙, 每次去服務端獲取資源, 需要帶著這把鑰匙, 只有自己的鎖芯(資源), 才能打開.。
但是如果鑰匙被別人拿了, 那別人就可以冒充你的身份, 去打開你的鎖芯, 從而獲取你的信息, 甚至挪用你的資金. 這是非常危險的.
XSS攻擊:
其就是利用站點開放的文本編輯並發布的功能, 從而造成攻擊,就是輸入javascript腳本, 竊取並投遞cookie信息到自己的站點.
比如攻擊者以一個普通用戶登錄進來,然後在輸入框中提交以下數據:
有了該session-id,攻擊者在會話有效期內即可獲得管理員的權限,並且由於攻擊數據已添加入數據庫,只要攻擊數據未被刪除,那麽攻擊還有可能生效,是持久性的。
Cookie的不安全就是因為這引起的。
Cookie防劫持預防
基於XSS攻擊, 竊取Cookie信息, 並冒充他人身份。
1) 方法一:
給Cookie添加HttpOnly屬性, 這種屬性設置後, 只能在http請求中傳遞, 在腳本中, document.cookie無法獲取到該Cookie值. 對XSS的攻擊, 有一定的防禦值. 但是對網絡攔截, 還是泄露了.
2)方法二:
在cookie中添加校驗信息, 這個校驗信息和當前用戶外置環境有些關系,比如ip,user agent等有關. 這樣當cookie被人劫持了, 並冒用, 但是在服務器端校驗的時候, 發現校驗值發生了變化, 因此要求重新登錄, 這樣也是種很好的思路, 去規避cookie劫持.
3)方法三:
cookie中session id的定時更換, 讓session id按一定頻率變換, 同時對用戶而言, 該操作是透明的, 這樣保證了服務體驗的一致性.
用大白話談談XSS與CSRF
CSRF攻擊是源於WEB的隱式身份驗證機制!WEB的身份驗證機制雖然可以保證一個請求是來自於某個用戶的瀏覽器,但卻無法保證該請求是用戶批準發送的!
如何防禦?
請求令牌(一種簡單有效的防禦方法):
首先服務器端要以某種策略生成隨機字符串,作為令牌(token),保存在 Session 裏。然後在發出請求的頁面,把該令牌以隱藏域一類的形式,與其他信息一並發出。在接收請求的頁面,把接收到的信息中的令牌與 Session 中的令牌比較,只有一致的時候才處理請求,處理完成後清理session中的值,否則返回 HTTP 403 拒絕請求或者要求用戶重新登陸驗證身份
令牌來防止 CSRF 有以下幾點要註意:
a.雖然請求令牌原理和驗證碼有相似之處,但不應該像驗證碼一樣,全局使用一個 Session Key。因為請求令牌的方法在理論上是可破解的,破解方式是解析來源頁面的文本,獲取令牌內容。如果全局使用一個 Session Key,那麽危險系數會上升。原則上來說,每個頁面的請求令牌都應該放在獨立的 Session Key 中。我們在設計服務器端的時候,可以稍加封裝,編寫一個令牌工具包,將頁面的標識作為 Session 中保存令牌的鍵。
b.在 ajax 技術應用較多的場合,因為很有請求是 JavaScript 發起的,使用靜態的模版輸出令牌值或多或少有些不方便。但無論如何,請不要提供直接獲取令牌值的 API。這麽做無疑是鎖上了大門,卻又把鑰匙放在門口,讓我們的請求令牌退化為同步令牌。
c.第一點說了請求令牌理論上是可破解的,所以非常重要的場合,應該考慮使用驗證碼(令牌的一種升級,目前來看破解難度極大),或者要求用戶再次輸入密碼(亞馬遜、淘寶的做法)。但這兩種方式用戶體驗都不好,所以需要產品開發者權衡。
d.無論是普通的請求令牌還是驗證碼,服務器端驗證過一定記得銷毀。忘記銷毀用過的令牌是個很低級但是殺傷力很大的錯誤。我們學校的選課系統就有這個問題,驗證碼用完並未銷毀,故只要獲取一次驗證碼圖片,其中的驗證碼可以在多次請求中使用(只要不再次刷新驗證碼圖片),一直用到。
如下也列出一些據說能有效防範 CSRF,其實效果甚微或甚至無效的做法:
a.通過 referer 判定來源頁面:referer 是在 HTTP Request Head 裏面的,也就是由請求的發送者決定的。如果我喜歡,可以給 referer 任何值。當然這個做法並不是毫無作用,起碼可以防小白。但我覺得性價比不如令牌。
b.過濾所有用戶發布的鏈接:這個是最無效的做法,因為首先攻擊者不一定要從站內發起請求(上面提到過了),而且就算從站內發起請求,途徑也遠遠不知鏈接一條。比如 <img src="./create_post.php" /> 就是個不錯的選擇,還不需要用戶去點擊,只要用戶的瀏覽器會自動加載圖片,就會自動發起請求。
c.在請求發起頁面用 alert 彈窗提醒用戶:這個方法看上去能幹擾站外通過 iframe 發起的 CSRF,但攻擊者也可以考慮用 window.alert = function(){}; 把 alert 弄啞,或者幹脆脫離 iframe,使用 Flash 來達到目的。
總體來說,目前防禦 CSRF 的諸多方法還沒幾個能徹底無解的。 作為開發者,我們能做的就是盡量提高破解難度。當破解難度達到一定程度,網站就逼近於絕對安全的位置了。
安全防範
CSRF(Cross-site request forgery,跨站請求偽造),是通過偽造請求,冒充用戶在站內進行操作
比如,點擊發帖後會進行如下GET請求
http://example.com/bbs/create_post.php?title=標題&content=內容
那麽,如果我們模擬了請求的鏈接,那麽只要有用戶點擊了這個鏈接,他就會在不知情的情況下發布了這一帖子,那麽刪貼,發郵件等等都可以進行偽造
http://example.com/bbs/create_post.php?title=攻擊&content=哈哈
如何防範 CSRF 攻擊
- CSRF 攻擊之所以能夠成功:是因為黑客可以完全偽造用戶的請求,該請求中所有的用戶驗證信息都是存在於 cookie 中,因此黑客可以在不知道這些驗證信息的情況下直接利用用戶自己的 cookie 來通過安全驗證
- 所以解決辦法是:在請求中放入黑客所不能偽造的信息,並且該信息不存在於 cookie 之中
- 驗證 HTTP Referer 字段
- 關鍵操作只接受POST請求,因為GET請求的參數攜帶在URL中,很容易進行模擬,而POST請求的參數在http body中
- 驗證碼,每次操作都需要用戶進行互動,從而簡單有效的防禦了CSRF攻擊,但是驗證碼太多,也會影響用戶體驗
- 可以在 HTTP 請求中以參數的形式加入一個隨機產生的 token,並在服務器端來驗證這個 token
- 可以在 HTTP 頭中自定義的屬性裏加入一個隨機產生的 token,通過XMLHttpRequest,可以給所有請求加上這個token,通過XMLHttpRequest 請求的地址不會被記錄到瀏覽器的地址欄,也不用擔心 token 會透過 Referer 泄露到其他網站中
註意:過濾用戶輸入的內容不能阻擋 CSRF,我們需要做的是過濾請求的來源
XSS(Cross Site Scripting,跨站腳本攻擊),是註入攻擊的一種,特點是不對服務器端造成任何傷害,而是通過一些正常的站內交互途徑
例如:發布評論,提交含有 JavaScript 的內容文本,如果服務器端沒有過濾或轉義掉這些腳本,作為內容發布到了頁面上,其他用戶訪問這個頁面的時候就會運行這些腳本,或者是一些未授權的操作
while (true) { alert("你關不掉我~"); }
在輸入框中輸入document.cookie
,可以直接獲得cookie
中的內容,所以,在重要的cookie
參數中加入httpOnly
屬性
XSS 是實現 CSRF 的諸多途徑中的一條,一般習慣上把通過 XSS 來實現的 CSRF 稱為 XSRF
如何防禦 XSS 攻擊
理論上,所有可輸入的地方沒有對輸入數據進行處理的話,都會存在XSS漏洞,防禦 XSS 攻擊最簡單直接的方法,就是過濾用戶的輸入
可以直接對用戶的輸入進行 HTML escape
<script>window.location.href=”http://www.baidu.com”;</script>
經過 escape 之後,就不能執行了
<script>window.location.href="http://www.baidu.com"</script>
XSS,CSRF,Cookie防劫持的處理