前端 input 輸入框可能被攻擊的幾種方式及防範

NingBo發表於2019-03-22

前言

最近看到一篇文章,文章講到輸入框有被 注入程式碼攻擊 的危險,自己做了一個小示例,發現確實有這樣的情況。

示例

先來看小示例吧,一個最簡單的留言功能,輸入框輸入資訊,然後把資訊插入頁面:

頁面效果

前端 input 輸入框可能被攻擊的幾種方式及防範

關鍵程式碼

<body>
	<div id="content"></div>
	<input id='input'>
	<input type="button" id='button' value="提交">
</body>
<script>
	const btn = document.getElementById('button');
	const myInput = document.getElementById('input');
	const content = document.getElementById('content');
	btn.onclick = ()=> {
            content.innerHTML = myInput.value
	};
</script>
複製程式碼

程式碼注入輸入框 可能引發攻擊的幾種方式

HTML 程式碼注入輸入框

在輸入框中輸入 <h1>哈哈,你的頁面結構被我破壞了</h1>,然後提交,效果如下:

前端 input 輸入框可能被攻擊的幾種方式及防範

<script> 標籤注入輸入框

在輸入框中輸入 <script> alert(0); </script> ,然後提交。
我們會發現沒有彈窗,這裡沒有執行 JavaScript 程式的原因是:HTML 5 中不執行由 innerHTML 插入的 <script> 標籤,但是在程式碼結構中可以看到被插入的程式碼片段。

前端 input 輸入框可能被攻擊的幾種方式及防範

其他不通過 <script> 標籤執行 JavaScript 程式的程式碼注入輸入框

不通過 <script> 標籤執行 JavaScript 的方式還是會有被攻擊的風險,比如 MDN 中舉到的例子: <img src='x' onerror='alert(1)'> ,我們輸入後可以看到程式是可以執行的:

前端 input 輸入框可能被攻擊的幾種方式及防範

防範

既然輸入框有被攻擊的風險,那我們就應該做好防範,好在 Vue 已經替我們最好了防範。如果沒有使用 Vue ,也有合適的解決辦法。

Vue 的防範原理

Vue 在動態插入元素的時候,會將標籤的 <> 等轉換為轉義字元 &lt&gt 等來避免 JavaScript 程式的執行,使用 Vue 通過輸入框插入程式碼後,插入的頁面的程式碼會被轉義如下:

前端 input 輸入框可能被攻擊的幾種方式及防範

未防範的情況下,插入頁面的程式碼如下:

前端 input 輸入框可能被攻擊的幾種方式及防範

原生 JavaScript 防範方法

我們可以使用和 Vue 同樣的防範方法,將 <>&'" 等符號替換成轉義字元來規避風險,這裡使用 zhangxiangliang 同學在 《每日 30 秒 ⏱ 大家一起被捕吧》 文章中寫的方法來做處理:

// 將輸入框的字串通過正則,將符號替換成轉義字元
const escapeHTML = str =>
    str.replace(/[&<>'"]/g, tag => ({
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        "'": '&#39;',
        '"': '&quot;'
    }[tag] || tag));
複製程式碼

總結

雖然有些攻擊的方式,在控制檯編輯後也能讓頁面錯亂,但如果我們有規避風險方法,還是不要給工作和公司帶來麻煩比較好。

參考資料

每日 30 秒 ⏱ 大家一起被捕吧: juejin.im/post/5c92c1…
MDN element.innerHTML:developer.mozilla.org/zh-CN/docs/…

相關文章