0x00 什么是预编译语句
SQL语句,说到底也是一种类似于编程语言的东西,目的是让程序员更友好的操纵数据库,既然这样,它肯定也存在一个SQL语句的编译过程,将其转化为数据库所能执行的命令。顾名思义,预编译语句就是将需要执行SQL语句预先进行编译后缓存起来,下次使用的时候直接越过了编译这步,理论上是会比普通的SQL查询拥有更好的性能。我这里的重点不是关注它的性能,而是大家都说,预编译可以防止SQL注入,事实是怎样的呢?我们平时说的参数化查询,又是怎么一回事?
0x01 搭建环境
我们需要了解应用程序和数据库交互时,一些支持预编译的模块(如PreparedStatement)进行了怎样的处理,数据库收到的究竟是怎样的数据。我们通过两种方式来观察传递结果:开启MySQL的日志记录,用wireshark抓包。
首先,打开MySQL的日志记录:
这里遇到了一点小坑,寻找my.ini
配置文件的时候,以为位置是在默认安装根目录下(C:\Program Files\MySQL\MySQL Server 5.7),结果发现并没有。查看文档,说依照以下顺序搜索配置文件:
%PROGRAMDATA%\MySQL\MySQL Server 5.7\my.ini
%PROGRAMDATA%\MySQL\MySQL Server 5.7\my.cnf
%WINDIR%\my.ini
%WINDIR%\my.cnf
C:\my.ini
C:\my.cnf
......
我在cmd里 echo %PROGRAMDATA%,结果输出的是:
接下来找到my.ini
,在 [mysqld]
中修改以下两个参数:
...
general-log=1 # 默认是0,1代表开启
general_log_file="E:/mysql/logs/mysql_general.log"
...
接下来我们新建一个简单的Java程序,来测试一下:
try {
Class.forName(name);//指定连接类型
conn = DriverManager.getConnection(url, user, password);//获取连接
pst = conn.prepareStatement("SELECT * FROM users WHERE `name`=?");//准备执行语句
pst.setString(