一、什么是SQL注入?
SQL是操作数据库数据的结构化查询语言,网页的应用数据和后台数据库中的数据进行交互时会采用SQL。SQL注入是指将Web页面的原URL、表单域或数据包输入的参数,修改拼接成SQL语句,传递给Web服务器,进而传给数据库服务器以执行数据库命令。当Web应用程序的开发人员对用户所输入的数据不进行过滤或验证(即存在注入点)就直接传输给数据库,就可能导致拼接的SQL被执行,获取数据库的信息以及提权,此时称发生了SQL注入攻击。
二、举个简单的例子
Web页面的某个表单项需要与后端服务器进行交互,用户输入的数据通过提交之后被后端解析到SELECT查询语句的WHERE字段后面,根据用户的输入查询对应的数据库内容。此时用户进行了非法输入,比如:在理想输入的后面加上“;DROP TABLE ***”,则后端在执行完毕正常的查询后会将数据库中的数据删除,严重威胁到数据库安全。又或者,用户在理想输入的后面加上“or ‘1’ = ‘1’”,则查询语句永远为真,用户会获取到该表的全部数据,有隐私泄露的风险。
三、如何防护
总的来说有以下几点:
- 永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度的策略。
- 永远不要使用动态拼装的SQL语句,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。
- 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。
- 应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装,把异常信息存放在独立的表中。
四、我的做法
2019年9月到2019年12月期间,我参与了银江股份有限公司的交通仿真系统的开发工作。该系统的开发后端连接了mapd数据库,涉及到大量的数据库查询工作。服务器中主要维护了三个表:各个路口的经纬度;各个路口一个月内的速度记录;各个路口一个月内的流量记录。前端需要用户输入查询的起止时间、用于过滤的速度阈值与时间阈值、路口ID等信息。这些用户的输入与后端拼接的动态SQL语句有着直接的关系,因此存在大量SQL注入点,为防范SQL注入,我当时做了如下工作:
- 数据库方面:新建了一个用于前后端交互连接数据库的普通用户,禁用该用户对数据库的修改权限(该系统没有对数据库的写入需求)。
- 前端过滤:使用正则表达式对用户输入的时间格式进行匹配,只有yyyy–mm–dd hh:mm:ss的时间输入才为合法输入;判断用户输入的流量与速度阈值是否是数值型,若非数值型,提示用户的输入不合法,请求重新输入。
下面附上当时设计的第一版功能界面(后面对此界面进行了调整):
五、感悟
作为一名Web应用开发人员,一定不要盲目相信用户的输入,要对用户输入的每一项数据进行严格的校验处理。这样做有两个好处:一是避免用户不小心输入错误导致后端报错;二是能够一定程度上防范SQL注入。
哪怕用户的输入不与数据库交互,也要对用户的输入进行合理性的检查,任何时候都要对用户的输入进行检查,因为——“用户是顽皮的小孩子,它们什么都不懂”。