前言
最近看到一篇文章,文章講到輸入框有被 注入程式碼攻擊 的危險,自己做了一個小示例,發現確實有這樣的情況。
示例
先來看小示例吧,一個最簡單的留言功能,輸入框輸入資訊,然後把資訊插入頁面:
頁面效果
關鍵程式碼
<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>
,然後提交,效果如下:
<script>
標籤注入輸入框
在輸入框中輸入 <script> alert(0); </script>
,然後提交。
我們會發現沒有彈窗,這裡沒有執行 JavaScript
程式的原因是:HTML 5
中不執行由 innerHTML
插入的 <script>
標籤,但是在程式碼結構中可以看到被插入的程式碼片段。
其他不通過 <script>
標籤執行 JavaScript
程式的程式碼注入輸入框
不通過 <script>
標籤執行 JavaScript
的方式還是會有被攻擊的風險,比如 MDN 中舉到的例子: <img src='x' onerror='alert(1)'>
,我們輸入後可以看到程式是可以執行的:
防範
既然輸入框有被攻擊的風險,那我們就應該做好防範,好在 Vue
已經替我們最好了防範。如果沒有使用 Vue
,也有合適的解決辦法。
Vue 的防範原理
Vue
在動態插入元素的時候,會將標籤的 <
、 >
等轉換為轉義字元 <
、 >
等來避免 JavaScript
程式的執行,使用 Vue
通過輸入框插入程式碼後,插入的頁面的程式碼會被轉義如下:
未防範的情況下,插入頁面的程式碼如下:
原生 JavaScript 防範方法
我們可以使用和 Vue
同樣的防範方法,將 <
、 >
、&
、 '
、 "
等符號替換成轉義字元來規避風險,這裡使用 zhangxiangliang 同學在 《每日 30 秒 ⏱ 大家一起被捕吧》 文章中寫的方法來做處理:
// 將輸入框的字串通過正則,將符號替換成轉義字元
const escapeHTML = str =>
str.replace(/[&<>'"]/g, tag => ({
'&': '&',
'<': '<',
'>': '>',
"'": ''',
'"': '"'
}[tag] || tag));
複製程式碼
總結
雖然有些攻擊的方式,在控制檯編輯後也能讓頁面錯亂,但如果我們有規避風險方法,還是不要給工作和公司帶來麻煩比較好。
參考資料
每日 30 秒 ⏱ 大家一起被捕吧: juejin.im/post/5c92c1…
MDN element.innerHTML:developer.mozilla.org/zh-CN/docs/…