前言
最近看到一篇文章,文章讲到输入框有被 注入代码攻击 的危险,自己做了一个小示例,发现确实有这样的情况。
示例
先来看小示例吧,一个最简单的留言功能,输入框输入信息,然后把信息插入页面:
页面效果

关键代码
<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.cn/post/684490…
MDN element.innerHTML:developer.mozilla.org/zh-CN/docs/…