前端 input 输入框可能被攻击的几种方式及防范

8,963 阅读2分钟

前言

最近看到一篇文章,文章讲到输入框有被 注入代码攻击 的危险,自己做了一个小示例,发现确实有这样的情况。

示例

先来看小示例吧,一个最简单的留言功能,输入框输入信息,然后把信息插入页面:

页面效果

关键代码

<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 在动态插入元素的时候,会将标签的 <> 等转换为转义字符 &lt&gt 等来避免 JavaScript 程序的执行,使用 Vue 通过输入框插入代码后,插入的页面的代码会被转义如下:

未防范的情况下,插入页面的代码如下:

原生 JavaScript 防范方法

我们可以使用和 Vue 同样的防范方法,将 <>&'" 等符号替换成转义字符来规避风险,这里使用 zhangxiangliang 同学在 《每日 30 秒 ⏱ 大家一起被捕吧》 文章中写的方法来做处理:

// 将输入框的字符串通过正则,将符号替换成转义字符
const escapeHTML = str =>
    str.replace(/[&<>'"]/g, tag => ({
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        "'": '&#39;',
        '"': '&quot;'
    }[tag] || tag));

总结

虽然有些攻击的方式,在控制台编辑后也能让页面错乱,但如果我们有规避风险方法,还是不要给工作和公司带来麻烦比较好。

参考资料

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