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