(四)前后端分離模式下的安全解決方案

2018-02-24 16:04 更新

原文:http://ued.taobao.org/blog/2014/05/midway-security/
作者:lorrylockie

前言

在前后端分離的開發(fā)模式中,從開發(fā)的角色和職能上來講,一個最明顯的變化就是:以往傳統(tǒng)中,只負責瀏覽器環(huán)境中開發(fā)的前端同學,需要涉獵到服務端層面,編寫服務端代碼。而擺在面前的一個基礎(chǔ)性問題就是如何保障Web安全?

本文就在前后端分離模式的架構(gòu)下,針對前端在Web開發(fā)中,所遇到的安全問題以及應對措施和注意事項,并提出解決方案。

跨站腳本攻擊(XSS)的防御

問題及解決思路

跨站腳本攻擊(XSS,Cross-site scripting)是最常見和基本的攻擊Web網(wǎng)站的方法。攻擊者可以在網(wǎng)頁上發(fā)布包含攻擊性代碼的數(shù)據(jù),當瀏覽者看到此網(wǎng)頁時,特定的腳本就會以瀏覽者用戶的身份和權(quán)限來執(zhí)行。通過XSS可以比較容易地修改用戶數(shù)據(jù)、竊取用戶信息以及造成其它類型的攻擊,例如:CSRF攻擊。

預防XSS攻擊的基本方法是:確保任何被輸出到HTML頁面中的數(shù)據(jù)以HTML的方式進行轉(zhuǎn)義(HTML escape)。例如下面的模板代碼:

<textarea name="description">$description</textarea>

這段代碼中的$description為模板的變量(不同模板中定義的變量語法不同,這里只是示意一下),由用戶提交的數(shù)據(jù),那么攻擊者可以輸入一段包含”JavaScript”的代碼,使得上述模板語句的結(jié)果變成如下的結(jié)果:

<textarea name="description">
</textarea><script>alert('hello')'</script>
</textarea>

上述代碼,在瀏覽器中渲染,將會執(zhí)行JavaScript代碼并在屏幕上alert hello。當然這個代碼是無害的,但攻擊者完全可以創(chuàng)建一個JavaScript來修改用戶資料或者竊取cookie數(shù)據(jù)。

解決方法很簡單,就是將$description的值進行html escape,轉(zhuǎn)義后的輸出代碼如下

<textarea name="description">
&lt;/textarea&gt;&lt;script&gt;alert(&quot;hello!&quot;)&lt;/script&gt;
</textarea>

以上經(jīng)過轉(zhuǎn)義后的HTML代碼是沒有任何危害的。

Midway的解決方案

轉(zhuǎn)義頁面中所有用戶輸出的數(shù)據(jù)

對數(shù)據(jù)進行轉(zhuǎn)義有以下幾種情況和方法:

1. 使用模板內(nèi)部提供的機制進行轉(zhuǎn)義

中途島內(nèi)部使用KISSY xtemplate作為模板語言。

在xtemplate實現(xiàn)中,語法上使用兩個中括號(?{{val}})解析模板數(shù)據(jù), ,默認既是對數(shù)據(jù)進行HTML轉(zhuǎn)義的,所以開發(fā)者可以這樣寫模板:

<textarea name="description">{{description}}</textarea>

在xtemplate中,如果不希望輸出的數(shù)據(jù)被轉(zhuǎn)義,需要使用三個中括號({{{val}}})。

2. 在Midway中明確的調(diào)用轉(zhuǎn)義函數(shù)

開發(fā)者可以在Node.js程序或者模板中,直接調(diào)用Midway提供的HTML轉(zhuǎn)義方法,顯示的對數(shù)據(jù)進行轉(zhuǎn)義,如下:

方法1:在Node.js程序中對數(shù)據(jù)進行HTML轉(zhuǎn)義

var Security= require('midway-security');
//data from server,eg {html:'</textarea>',other:""}
data.html =Security.escapeHtml(data.html);
xtpl = xtpl.render(data);

方法2:在模板中對HTML數(shù)據(jù)進行HTML轉(zhuǎn)義

<textarea name="description">Security.escapeHtml({{{description}}})</textarea>

注意:只有當模板內(nèi)部沒有對數(shù)據(jù)進行轉(zhuǎn)義的時候才使用Security.escapeHtml進行轉(zhuǎn)義。 否則,模板內(nèi)部和程序會兩次轉(zhuǎn)義疊加,導致不符合預期的輸出。

推薦:如果使用xtemplate,建議直接使用模板內(nèi)置的{{}}進行轉(zhuǎn)義; 如果使用其他模板,建議使用Security.escapeHtml進行轉(zhuǎn)義。

過濾頁面中用戶輸出的富文本

你可能會想到:“其實我就是想輸出富文本,比如一些留言板、論壇給用戶提供一些簡單的字體大小、顏色、背景等功能,那么我該如何處理這樣的富文本來防止XSS呢?”

1. 使用Midway中Security提供的richText函數(shù)

Midway中提供了richText方法,專門用來過濾富文本,防止XSS、釣魚、cookie竊取等漏洞。

有一個留言板,模板代碼可能如下:

<div class="message-board">
{{{message}}}
</div>

因為message是用戶的輸入數(shù)據(jù),其留言板的內(nèi)容,包含了富文本信息,所以這里在xtemplate中,使用了三個大括號,默認不進行HTML轉(zhuǎn)義;那么用戶輸入的數(shù)據(jù)假如如下:

<script src="https://atts.w3cschool.cn/attachments/image/cimg/pre>

上述的富文本數(shù)據(jù)如果直接輸出到頁面中,必然會導致eval.com站點的js注入到當前頁面中,造成了XSS攻擊。為了防止這個漏洞,我們只要在模板或者程序中,調(diào)用Security.richText方法,處理用戶輸入的富文本。

調(diào)用方法與escapeHtml類似,有如下兩種方式

方法1: 直接在Node.js程序中調(diào)用

message =Security.richText(message);
var html = xtpl.render(message)

方法2: 在模板中調(diào)用

<div class="message-board">
Security.richText({{{message}}})
</div>

通過調(diào)用Security的richText方法后,最終的輸出如下:

<div class="message-board">
<span style="color:red;font-size:20px;">我在留言中</span>
</div>

可以看出,首先:會造成XSS攻擊的script標簽被直接過濾掉;同時style標簽中CSS屬性position:fixed;樣式也被過濾了。最終輸出了無害的HTML富文本

了解其他可能導致XSS攻擊的途徑

除了在頁面的模板中可能存在XSS攻擊之外,在Web應用中還有其他幾個途徑也可能會有風險。

1. 出錯頁面的漏洞

一個頁面如果找不到,系統(tǒng)可能會報一個404 Not Found的錯誤,例如:http://localhost/page/not/found

404 NotFound
Page /page/not/found does not exsit

很顯然:攻擊者可以利用這個頁面,構(gòu)造一個類似這樣的連接,http://localhost/%3Cscript%3Ealert%28%27hello%27%29%3C%2Fscript%3E,并引誘受害者點擊 ;假如出錯頁面未對輸出變量進行轉(zhuǎn)義的話,那么連接中隱藏的?<script>alert('hello')</script>?將會被執(zhí)行。

在express中,發(fā)送一個404頁面的方法如下

res.send(404,'Sorry,we don\'t find that!')

這里就需要開發(fā)者注意錯誤頁面(404或者其他錯誤狀態(tài))的處理方式。如果錯誤信息的返回內(nèi)容帶有路徑信息(其實更準確的講,是用戶輸入信息),就一定要進行escapeHtml了。

后續(xù),錯誤處理的安全機制,會在Midway框架層面中完成。

Midway解決方案的補充說明

其他模板引擎

Midway默認支持xtemplate模板,但將來也有可能支持其他模板:如jade、mustache、ejs等。目前在主流模板中,都提供了默認轉(zhuǎn)義和不轉(zhuǎn)義的輸出變量寫法,需要開發(fā)者特別留意其安全性。

關(guān)于escape的其他支持

除了對頁面中輸出的普通數(shù)據(jù)和富文本數(shù)據(jù),一些場景中也還包含其他可能需要轉(zhuǎn)義的情況,Midway提供了如下幾個常用的轉(zhuǎn)義方法,供開發(fā)者使用:

  • escapeHtml 過濾指定的HTML中的字符,防XSS漏洞
  • jsEncode 對輸入的String進行JavaScript 轉(zhuǎn)義 對中文進行unicode轉(zhuǎn)義,單引號,雙引號轉(zhuǎn)義
  • escapeJson 不破壞JSON結(jié)構(gòu)的escape函數(shù),只對json結(jié)構(gòu)中name和vaule做escapeHtml處理
  • escapeJsonForJsVar 可以理解就是jsEncode+escapeJson

例子如下

var jsonText ="{\"<script>\":\"<script>\"}";
console.log(SecurityUtil.escapeJson(jsonText));// {"&lt;script&gt;":"&lt;script&gt;"}
var jsonText ="{\"你好\":\"<script>\"}";
console.log(SecurityUtil.escapeJsonForJsVar(jsonText));//{\"\u4f60\u597d\":\"&lt;script&gt;\"}
var str ="alert(\"你好\")";
console.log(SecurityUtil.jsEncode(str));// alert(\"\u4f60\u597d\")

跨站請求偽造攻擊(CSRF)的預防

問題及解決思路

名詞解釋:?表單:泛指瀏覽器端用于客戶端提交數(shù)據(jù)的形式;包括a標簽、ajax提交數(shù)據(jù)、form表單提交數(shù)據(jù)等,而非對等于HTML中的form標簽。

跨站請求偽造(CSRF,Cross-site request forgery)是另一種常見的攻擊。攻擊者通過各種方法偽造一個請求,模仿用戶提交表單的行為,從而達到修改用戶的數(shù)據(jù)或執(zhí)行特定任務的目的。

為了假冒用戶的身份,CSRF攻擊常常和XSS攻擊配合起來做,但也可以通過其它手段:例如誘使用戶點擊一個包含攻擊的鏈接。

解決CSRF攻擊的思路分如下兩個步驟

  1. 增加攻擊的難度。GET請求是很容易創(chuàng)建的,用戶點擊一個鏈接就可以發(fā)起GET類型的請求,而POST請求相對比較難,攻擊者往往需要借助JavaScript才能實現(xiàn);因此,確保form表單或者服務端接口只接受POST類型的提交請求,可以增加系統(tǒng)的安全性。
  2. 對請求進行認證,確保該請求確實是用戶本人填寫表單或者發(fā)起請求并提交的,而不是第三者偽造的。

一個正常用戶修改網(wǎng)站信息的過程如下

  • 用戶請求修改信息(1) -> 網(wǎng)站顯示用戶修改信息的表單(2) -> 用戶修改信息并提交(3) -> 網(wǎng)站接受用戶修改的數(shù)據(jù)并保存(4)

而一個CSRF攻擊則不會走這條路線,而是直接偽造第2步用戶提交信息

  • 直接跳到第2步(1) -> 偽造要修改的信息并提交(2) -> 網(wǎng)站接受攻擊者修改參數(shù)數(shù)據(jù)并保存(3)

只要能夠區(qū)分這兩種情況,就能夠預防CSRF攻擊。那么如何區(qū)分呢? 就是對第2步所提交的信息進行驗證,確保數(shù)據(jù)源自第一步的表單。具體的驗證過程如下:

  • 用戶請求修改信息(1) -> 網(wǎng)站顯示用于修改信息的空白表單,表單中包含特殊的token同時把token保存在session中(2) -> 用戶修改信息并提交,同時發(fā)回token信息到服務端(3) -> 網(wǎng)站比對用戶發(fā)回的token和session中的token,應該一致,則接受用戶修改的數(shù)據(jù),并保存

這樣,如果攻擊者偽造要修改的信息并提交,是沒辦法直接訪問到session的,所以也沒辦法拿到實際的token值;請求發(fā)送到服務端,服務端進行token校驗的時候,發(fā)現(xiàn)不一致,則直接拒絕此次請求。

Midway解決方案

禁用GET提交表單

如果服務端不接受GET方式提交的表單數(shù)據(jù),那么將會給攻擊者帶來非常大的難度;因為在頁面上構(gòu)造一個a標簽href屬性或者img標簽src屬性來構(gòu)造一個請求是非常容易的,但是如果要POST提交,就必須要通過腳本才可以實現(xiàn)。

用CSRF token驗證請求

因為Midway不涉及到淘寶分布式session及token校驗這一層面邏輯,所以在Midway框架中,只將token在server和客戶端之間進行轉(zhuǎn)發(fā),本身不做實際的校驗工作。流程如下:

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號