接口防sql注入的调研
注入的来源
http请求的路径、参数和header,比如cookie等都可能作为sql注入的来源。
在实际的开发工作中,因为现有框架中header、路径作为参数直接查询数据库的使用比较少。因此,主要处理参数sql注入。
防止sql注入PHP已知方案
未经转义的参数直接作为sql语句发给db就会发生sql注入,防止sql注入主要有以下几种方式:
- 强类型参数校验和转义,禁止特殊字符的参数传递。
- 框架和数据库统一提供的PREPARE, EXECUTE语法。
- 读写分离。
需要注意的是addslashes和mysql_real_escape_string都不能作为防SQL注入的方式。原因请参考:
https://blog.csdn.net/qq_36705093/article/details/79865601
详细说明
强类型参数校验和转义
1. thinkphp框架input()帮助函数提供了以下几种参数转义:`d`:转义int类型,`a`:转义数组类型,`f`: 转义浮点类型, `b`:转义bool类型,`s`: 转义字符串类型.
2. 也可以用intval, doubleval, floatval相关的函数进行参数过滤。识别无效的参数返回。
prepare, EXECUTE语法
thinkphp框架提供了prepare, execute语法来处理参数。详细的mysql prepare语法可以查看:
执行步骤:
- 发送sql语句。
- 设置变量。
- 使用变量执行语句。
举个例子:
prepare example from 'select * from sdb_user where id=?'; set @a=1; EXECUTE example USING @a;
步骤1中的sql语句会被mysql认为是需要执行的部分。步骤2, 3的语句传入的变量不会被mysql执行。因此这种方式是最安全的mysql防注入的方式。对于thinkphp框架来说,是语句部分还是需要绑定的参数,是根据是否是变量来标识的。对于直接字符串拼接的部分,框架会认为是是sql语句而直接在步骤1发送给mysql,如果这部分有参数拼接就可能发生sql注入。
读写分离
thinkphp提供了方便的读写分离的配置。对于大部分业务来说,读的接口都是在其中占据较大的部分,因此可以使用读写分离的方式来降低sql注入时对db造成严重破坏的概率,比如改写数据,删库等。
主要包含以下database.php配置
<?php return [ "hostname":[ "127.0.0.1", //master "127.0.0.1" //readonly ], "username": [ "foo_write", //master "foo_read", //readonly ], "password": [ "bar_write", //master "bar_read", //readonly ], 'hostport' => '3306', 'deploy' => 1, 'rw_separate' => true, ];
因此使用tp框架防止sql注入可以做以下改进:
- 强类型参数校验。
- 使用参数的方式传递查询条件,禁止直接拼接参数。
- 读写分离。
by: zhangfeng