如何从根本上防止 SQL 注入

发布时间:2018-12-18 16:26:37编辑:丝画阁阅读(1099)

SQL注入本质上是数据和语句的混淆。在数据被拼入SQL模版变成SQL片段的时候,正是防止SQL注入漏洞产生的最佳时机,这时候什么是数据什么是语句分得最清楚,只要使用强类型转化就可以避免数据和语句的混淆,而无需特征匹配或语法分析。一但失去这个时机,红豆和绿豆混在一起,再想摘出来就难了,难免会被绕过。

参数化只是捕捉这个时机并有效处理的最佳手段而已,这里“最佳”是包含了有效性、成本、可控等若干方面的考量。看到很多人粗暴的将其理解为“参数化能防SQL注入”,然后举各种反例,也挺无奈的。

相关讨论中,很多人混淆了“抵御SQL注入攻击”和“防止SQL注入漏洞的产生”两个概念,没有做过企业级安全支持的人——无论他是其他领域多NB的专家,还是对安全一知半解的工程师——也很难真正理解后者的真实含义和必要性,而将其看作数据库系统本身的弱点加以防御,从而陷入特征匹配的攻防纠缠中。

还有很多人混淆了“我如何防止SQL注入漏洞的产生”和“我如何避免公司里的工程师产生SQL注入漏洞”。刺客和军官本身就是两个职业,在高深的武艺、精良的装备之外,还有很多诸如组织形式、流程、士气、主要矛盾主要方面这样的问题。作为一个公司级别的解决方案,如果在数据库层面没法保证让程序员撒花的写代码也能避免SQL注入攻击的话,那你就不得不去好好面对“我如何避免公司里的工程师产生SQL注入漏洞”的问题。工程师不可能都是安全方面的专家,你也不可能让工程师写代码的时候始终崩着弦去考虑如何避免OWASP TOP 10这类问题,在这个前提下怎么解决问题,似乎安全框架+编码规范+白盒检查成了最好的选择。

SQL注入的危害性使得企业不得不追求彻底防御,不能接受潜在的绕过风险。而彻底防御又只能在生成SQL片段的时机实现,控制这个时机的是开发工程师而不是数据库,因此这是个系统问题和管理问题,而不是技术问题,至少不是纯粹的技术问题,特别不是SQL注入检测技术的问题。

回到问题本身,SQL注入问题既不能“靠用户(开发者也是用户)的自觉去避免”,也不能完全脱离用户(开发者也是用户)而指望数据库层面去避免。对于那些不了解SQL注入漏洞细节或不关心SQL注入漏洞或没精力去关心SQL注入漏洞的工程师,你要给他们一条尽可能简单可行透明的方案来避免SQL注入漏洞,告诉他这样写就可以了,这就是安全框架;然后告诉他或者让他的老大告诉他你必须这样写,这就是安全编码规范;然后你有手段在他没有这样写的时候能够检查出来(这比检查出漏洞要容易)并推动他改正,这就是白盒检查。

我们现在的互联网产品SQL注入漏洞仍然层出不穷,并不是这套思路有问题,相反恰恰是这套思路没有完善。

一方面是框架方案本身不完善,以SQL注入漏洞为例,参数化是防SQL注入框架级方案的重要部分,但仅靠参数化没法很好满足开发过程中一些常见需求,如逗号分割的id列表问题、排序标记的问题等等(其实这些问题真要用参数化的方案解决也可以),使得开发更愿意在这些地方使用非参数化或伪参数化的方法(比如拼接SQL片段后再把整个片段当作参数扔进去exec)。这些问题在参数化的基础上,再加以改进,仍然守着拼接SQL片段时进行强类型转换的思路,仍然是能很好解决的,也就是继续完善参数化方案的问题,而不是看上去那样“参数化解决不了问题”。

另一方面,安全编码规范的制定、培训、流程建设和实施保证上也做得远远不到位,开发leader们更希望后面的数据库或者前面的安全防御上能有手段去解决SQL注入问题,对于安全工程师来说,设置并维护几个特征串、语法分析场景也远比做那些安全框架、编码规范、白盒扫描来得要轻松实在,彼此在心照不宣中度过今天,自然不能指望明天能彻底踏实。

关键字