Vue过滤特殊字符后为什么SQL注入还能被绕过?
在Vue项目里处理搜索框输入时,我给后端API加了引号过滤,但测试SQL注入时发现还是能绕过…
具体场景是用户输入搜索词会拼接SQL语句,我在前端用了正则过滤单双引号,但输入” OR 1=1–%20测试时,后端居然返回了全部数据。代码是这样的:
<template>
<input v-model="searchTerm" @input="filterChars">
</template>
<script>
export default {
data() {
return { searchTerm: '' }
},
methods: {
filterChars() {
this.searchTerm = this.searchTerm.replace(/['"]/g, '')
}
}
}
</script>
明明把引号都替换了,为什么攻击者还能用双引号构造注入?测试时用的是Postman传参,后端是PHP的mysqli,难道过滤应该在后端做?但前端过滤不是应该作为第一道防线吗?
第一步,我们先说为什么你的过滤会被绕过。虽然你在前端替换了单双引号,但SQL注入并不一定依赖引号来构造恶意语句。比如你提到的输入" OR 1=1--%20,这里的双引号可能根本不需要,攻击者可以用其他方式构造逻辑表达式,甚至利用数值比较、注释符等手段完成注入。而且即使你过滤了引号,后端拼接SQL时如果没有正确处理参数,依然会被注入。
第二步,解决这个问题的关键在于后端,而不是前端。前端的过滤只能作为用户体验优化的一部分,比如防止用户误输入非法字符,但它绝不能作为安全防线。真正防止SQL注入的方式是使用参数化查询或者预处理语句。下面我给你一个PHP后端的示例代码,展示如何正确处理SQL查询:
上面这段代码的核心是使用了
prepare和bind_param方法,这样无论用户输入什么内容,都会被当作参数处理,而不会直接拼接到SQL语句中。即使输入中包含恶意代码,也不会影响SQL语句的执行。第三步,如果你还想在前端做一些额外的安全措施,可以补充一些校验规则,但这只是为了提升用户体验,而不是为了安全。比如你可以限制用户输入长度,或者禁止输入某些特殊符号,但这些都不能替代后端的参数化查询。
最后再强调一下,前端的安全措施只是锦上添花,真正的安全必须依赖后端的正确实现。SQL注入的根本原因在于后端拼接了未经过滤的用户输入,所以一定要用参数化查询或者ORM框架来避免手动拼接SQL语句。
其实开发的时候经常遇到这种问题,有时候会觉得多写几行代码麻烦,但安全问题一旦出事就是大麻烦,还是老老实实写好预处理吧。
你看攻击者用的是双引号,但你的正则只替换单双引号字符,而SQL注入可以用十六进制编码、注释符甚至不需要引号。像
OR 1=1--这种本来就不依赖引号,拼接SQL的时候直接闭合条件就行,你前端删不删除引号都影响不了最终请求体。更关键的是,Postman绕过Vue的input事件太容易了,直接发POST请求,根本不会触发你那个filterChars方法。你在前端v-model上处理,只能拦住从界面输入的值,拦不住绕过前端的请求。
真正靠谱的做法是后端用预处理语句(prepared statement),PHP的话就是mysqli_prepare或者PDO:
别再指望前端过滤能防注入了,那顶多叫输入净化,连第一道防线都算不上。真正的防线永远在服务端,用参数化查询,别拼SQL字符串。前端加个提示也好,但别让它背锅安全责任。