输入过滤与消毒有何区别?结合参数化语句能否有效防护SQLi、XSS?
1. 输入过滤与输入消毒的核心区别
二者是完全不同的输入处理逻辑:
- 输入过滤(输入验证):核心是校验输入是否符合业务预设规则,比如要求输入为手机号、整数、合法邮箱,不符合规则就直接拦截丢弃,不会进入后续业务流程。
- 输入消毒(输入清理):核心是消除输入中的危险字符,不会直接拦截输入,而是对输入内容做转义、裁剪等处理,把可能触发恶意代码执行的内容转为普通文本,处理后的内容会进入后续业务流程。
2. 对filter_input()与filter_var()的认知修正
你当前的理解存在一定偏差,两个函数的实际定位如下:
相同点
二者都是PHP官方提供的输入处理函数,都支持两类处理逻辑:验证类逻辑(校验是否符合规则,不符合返回false)、消毒类逻辑(处理危险字符后返回安全内容)。
核心区别
filter_input()是直接从外部输入源(GET/POST/COOKIE等)获取并处理数据,不需要你先读取$_GET/$_POST等超全局变量再处理,可以避免开发者忘记处理直接调用原生超全局变量的风险。它不是自动把SQL内容转为普通字符串,你需要显式指定对应的过滤器才会执行对应处理。filter_var()是对任意已存在的变量做处理,变量可以是外部输入的,也可以是代码内部生成的,它不是只有验证能力:指定验证类过滤器(比如FILTER_VALIDATE_EMAIL)时它做校验,指定消毒类过滤器(比如FILTER_SANITIZE_SPECIAL_CHARS)时它就会执行输入清理。
举个例子:
filter_var('test<svg onload=alert(1)>@mail.com', FILTER_SANITIZE_EMAIL)会返回处理后的结果test@mail.com,自动移除了输入中的恶意标签内容,这就是消毒能力的体现。
3. 结合参数化语句的防护效果
二者和参数化语句搭配,确实可以覆盖绝大多数常见的SQLi、XSS攻击场景:
针对SQL注入
只要严格使用参数化预处理语句操作数据库,本身就能防住99%以上的SQL注入场景,因为参数化会强制把所有传入的参数视为普通字符串,数据库不会把参数内容解析为SQL指令执行。filter_input()/filter_var()可以作为纵深防御手段额外添加,比如接收用户ID时用FILTER_VALIDATE_INT做校验,不符合规则直接拦截,进一步降低风险。
针对XSS攻击
参数化语句只能避免恶意XSS代码被写入数据库,无法防御输出环节触发的XSS。如果搭配filter_input()/filter_var()的消毒类过滤器提前处理用户输入,再配合输出时根据输出场景做对应转义(输出到HTML就转义HTML特殊字符,输出到JS就转义JS特殊字符),可以覆盖绝大多数反射型、存储型XSS场景。仅DOM型XSS属于前端逻辑漏洞,后端这两类手段无法覆盖,需要前端做输出处理。
内容的提问来源于stack exchange,提问作者user17177623

