SQL注入(SQL injection)攻击,是发生于应用程序与数据库层的安全漏洞。指的是用户是在输入的字符串之中注入SQL指令,进而发动攻击的行为。
如果在程序当中忽略了对用户输入字符的检查,则很有可能使得攻击者恶意注入的指令被数据库误认为是正常的SQL指令而运行,进而使得系统遭到破坏或者是入侵。
栈溢出,SQL注入攻击等,这一类注入攻击的本质,都是把用户输入的数据误当作了代码来执行。XSS攻击,在本质上也属于是一种针对HTML的注入攻击。
换成SQL注入,那就是用户提交的数据,被数据库系统编译而产生了服务提供者预料之外的非“数据”行为,注入攻击能够得以实施的两个关键条件在于:
第二步拼接的过程极为关键,正是这个步骤导致了注入的发生。
当我们访问动态网页时, web服务器会向数据访问层发起SQL查询请求,如果权限验证通过就会执行SQL语句,而很多时候这类SQL查询请求并不是固定的格式,而是要结合用户的输入数据来动态构造的。
如果用户故意输入恶意构造的SQL代码,而某些程序中又恰好编写了不安全的代码、对于变量处理不当,或者是没有对当前用户提交的数据类型进行校验,以及未对动态构造的SQL语句使用的参数进行审查,则都有可能使得非法分子构造非法的SQL语句或字符串,进而造成SQL注入攻击。
防范这类问题的方法有很多,注入严格检查和过滤用户提交的数据等,使用安全的存储过程和安全的编码函数来对抗SQL注入,有一个很重要的方法那便是使用预编译语句来保证SQL语句语义的不变性,从而摆脱了SQL语句的动态构造过程。
比起检查和过滤等方法,数据库预编译能够绝对避免数据变成代码被执行,时刻将数据和所要执行的代码隔离开来。通过在SQL语句中放置占位符来,然后将带有占位符的SQL语句传给数据库编译,执行的时候才将用户输入的数据作为执行的参数传给用户这一方法,使得其能够拥有防止SQL注入攻击的能力。
这样的操作,使得SQL语句在书写的时候不再需要拼接,而是通过用户输入的内容来自动填充预设SQL语句的配位符,从而避免通过程序判断生成SQL语句。
虽然没有控制用户的输入数据,但是从根本上断绝了用户数据被送到SQL解释器进行编译和执行的过程,也就避免了“数据”越权上位,成为“代码”,成为SQL语句查询逻辑的一部分了。
之前还写过一篇SQL注入相关的文章,里面举了一个关于SQL注入的小栗子,感兴趣的可以看看
愈发严格的过滤手段、预编译语句的使用、许多成熟框架与组件的不断更迭和推广,使得许多SQL注入攻击都消声觅迹了,看到参数就加个单引号的事情应该再也不会发生了。
但是,SQL注入作为一个古老的攻击方式,并不会轻易地消失。
但是,倘若有人因为SQL注入攻击存在的问题,而放弃使用SQL,那么这无疑是因噎废食的行为。
因为,这不仅仅是SQL语言的问题,而是只要有数据和代码未曾分离的地方,便都是注入攻击的可寻之地。