2019独角兽企业重金招聘Python工程师标准>>>

只要你学JDBC,基本上所有的人都会和你说,Statement不能防止SQL注入, PreparedStatement能够防止SQL注入. 基本上参加工作了一段时间之后还是这么认为的, 没错, 这句是没有问题的, 但到底如何进行SQL注入?怎么直观的去了解SQL注入?这还是需要花一定的时间去实验的. 前提:以下的测试都是在一种理想环境下 首先准备好数据库环境, 以下是数据库的schema:

Sql代码
  1. create database java_mysql;
  2. use java_mysql;
  3. drop table if exists pstest;
  4. create table pstest(
  5. id int(10) not null primary key auto_increment,
  6. name varchar(32),
  7. age int(3)
  8. );
  9. insert into pstest (name, age) values ('Tom', 23);
  10. insert into pstest (name, age) values ('Tom1', 23);
  11. insert into pstest (name, age) values ('Tom2', 23);
  12. insert into pstest (name, age) values ('Tom3', 23);
  13. insert into pstest (name, age) values ('Tom4', 23);
  14. insert into pstest (name, age) values ('Tom5', 23);
以上就是建立了pstest表, 并插入了一些测试数据.
1. 测试Statement
Java代码
  1. public class StatementTest {
  2. public static void main(String[] args) throws SQLException {
  3. Connection con = null;
  4. Statement stmt = null;
  5. // name很强大, 传入了这么多东西
  6. String name = "Tom';delete from pstest;select * from pstest where name='Tom";
  7. String sql = createSql(name);   // SQL
  8. System.out.println(sql);
  9. try {
  10. con = DBConn.getConnection();
  11. stmt = con.createStatement();
  12. stmt.execute(sql);
  13. } catch(Exception e) {
  14. e.printStackTrace();
  15. } finally {
  16. stmt.close();
  17. con.close();
  18. }
  19. }
  20. // 根据参数的name参数查询
  21. private static String createSql(String name) {
  22. String sql = "select id, name, age from pstest ";
  23. // 拼接一下SQL
  24. if(name != null && name.length() != 0) {
  25. sql += "where name ='" + name + "'";
  26. }
  27. return sql;
  28. }
  29. }

数据库连接的URL为:
Java代码
  1. "jdbc:mysql://localhost:3306/java_mysql";
其实上面的意图很简单:
Tom';delete from pstest;select * from pstest where name='Tom
就是想先执行一条SQL查询语句,然后把表的数据删除。
这只是理想环境. 实际上要想传入这么复杂的数据, 真的很难想象

这里将URL单独拎出来是有作用的, 继续看下面
Run一下StatementTest. 会发现报异常了:

Java代码
  1. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'delete from pstest;select * from pstest where name='Tom'' at line 1
想法很简单, 现实很残酷, 未能如所愿.
看到这里,你也应该想到了Statement的execute(String sql)默认是只能执行一条SQL的.
若想让execute(String sql)能够同时只能几条SQL语句, 怎么办?修改连接的URL:

Java代码
  1. jdbc:mysql://localhost:3306/java_mysql?allowMultiQueries=true
重点是allowMultiQueries=true这个参数
再来Run一下StatementTest. OK,没有报任何的异常.打印的SQL为:

Sql代码
  1. select id, name, age from pstest where name ='Tom';delete from pstest;select * from pstest where name='Tom';

上面的SQL到底做了什么呢?

我们先观察一下:第一条是查询SQL, 第二条是delete, 第三条是查询SQL,其实第一条和第三条是一样的.
为了直观的看上面SQL的执行效果, 我们再次执行下最开始的schema.sql
这时候数据库有6条数据
Sql代码
  1. mysql> select * from pstest;
  2. +----+------+------+
  3. | id | name | age  |
  4. +----+------+------+
  5. |  1 | Tom  |   23 |
  6. |  2 | Tom1 |   23 |
  7. |  3 | Tom2 |   23 |
  8. |  4 | Tom3 |   23 |
  9. |  5 | Tom4 |   23 |
  10. |  6 | Tom5 |   23 |
  11. +----+------+------+
执行一下
Sql代码
  1. select id, name, age from pstest where name ='Tom';delete from pstest;select * from pstest where name='Tom';
这时候可以看到MySQL客户端
Sql代码
  1. mysql> select id, name, age from pstest where name ='Tom';delete from pstest;select * from pstest where name='Tom';
  2. +----+------+------+
  3. | id | name | age  |
  4. +----+------+------+
  5. |  1 | Tom  |   23 |
  6. +----+------+------+
  7. 1 row in set (0.00 sec)                 -- 执行第一条查询SQL
  8. Query OK, 6 rows affected (0.05 sec)    -- 执行第二条delete语句, Oh, No, 数据库全部的6条数据被删除了
  9. Empty set (0.00 sec)                     -- 执行第三条SQL查询, 没有查询到任何数据
上面的注释已经写好了,就不多说了。
这时候的确已经实现了SQL注入.
2. 测试PreparedStatemet

Java代码
  1. public class PreparedStatementTest {
  2. public static void main(String[] args) throws SQLException {
  3. Connection con = null;
  4. PreparedStatement ps = null;
  5. ResultSet rs = null;
  6. String sql = "select id, name, age from pstest where name = ? ";
  7. try {
  8. con = DBConn.getConnection();
  9. ps = con.prepareStatement(sql);
  10. ps.setString(1, "Tom';delete from pstest;select * from pstest where name='Tom");
  11. rs = ps.executeQuery();
  12. } catch(Exception e) {
  13. e.printStackTrace();
  14. } finally {
  15. rs.close();
  16. ps.close();
  17. con.close();
  18. }
  19. }
  20. }
直接Run一下,OK,也没出现任何的异常,数据库中的数据也还在
但是我们到底执行了什么样的SQL, 查看MySQL的日志.
这里简单提下MySQL的日志,可以在my.ini下配置

Sql代码
  1. [mysqld]
  2. log=MySQL_Log    # 在这里加上日志名称

这时候会在MySQL/MySQL Server 5.1/Data/目录下生成MySQL_Log文件, 里面记录的就是日志了.

好了,回到正题,看一下刚刚PreparedStatementTest执行的SQL,在MySQL_Log中查看
Sql代码
  1. 120719 15:54:25      23 Connect   root@localhost on java_mysql
  2. 23 Query /* mysql-connector-java-5.1.20-SNAPSHOT ( Revision: ${bzr.revision-id} ) ...
  3. 23 Query SHOW WARNINGS
  4. 23 Query /* mysql-connector-java-5.1.20-SNAPSHOT ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increment_increment
  5. 23 Query SHOW COLLATION
  6. 23 Query SET character_set_results = NULL
  7. 23 Query SET autocommit=1
  8. 23 Query select id, name, age from pstest where name = 'Tom';delete from pstest;select * from pstest where name='Tom'
  9. 23 Quit
重点是最后一条SQL.
因为数据库中的数据都还在,我们就直接执行这条SQL

Sql代码
  1. select id, name, age from pstest where name = 'Tom';delete from pstest;select * from pstest where name='Tom'
查看MySQL的客户端
Sql代码
  1. mysql> select id, name, age from pstest where name = 'Tom';delete from pstest;select * from pstest where name='Tom';
  2. Empty set (0.00 sec)                     -- 就执行了这一条查询的SQL语句
可以看到什么的字符串已经被转义了.
让我们来看一下转义字符:

Sql代码
  1. mysql> select 'Tom';delete';
  2. +-------------+
  3. | Tom';delete |
  4. +-------------+
  5. | Tom';delete |
  6. +-------------+
  7. 1 row in set (0.00 sec)
总结:其实从上面的测试中已经看出了。的确Statement是不安全的, 可以进行SQL注入, 而PreparedStatement可以防止SQL注入。就好比上面我们想在做查询的时候将pstest中的全部数据都删除掉一样. 前面已经说过这是在理想的环境下做的测试. 在真正的环境中,就想这么简单的实现SQL注入, 基本上是不可能的。而且Statemenet,让它执行execute(String sql)的时候同时执行多条SQL, 基本上不可能会去这么做的.
其实,关于Statement的execute(String sql)语句能够同时执行多条SQL语句, 可以看MySQL自带的测试例子:
可查看testsuite.regression包下的ResultSetRegressionTest类:

Java代码
  1. public class ResultSetRegressionTest extends BaseTestCase {
  2. public void testBug33678() throws Exception {
  3. if (!versionMeetsMinimum(4, 1)) {
  4. return;
  5. }
  6. createTable("testBug33678", "(field1 INT)");
  7. // allowMultiQueries=true设置
  8. Connection multiConn = getConnectionWithProps("allowMultiQueries=true");
  9. Statement multiStmt = multiConn.createStatement();
  10. try {
  11. multiStmt.setFetchSize(Integer.MIN_VALUE);
  12. // 一次性执行多条SQL语句
  13. multiStmt
  14. .execute("SELECT 1 UNION SELECT 2; INSERT INTO testBug33678 VALUES (1); UPDATE testBug33678 set field1=2; INSERT INTO testBug33678 VALUES(3); UPDATE testBug33678 set field1=2 WHERE field1=3; UPDATE testBug33678 set field1=2; SELECT 1");
  15. // 以下代码省略...
  16. }
  17. }

转载于:https://my.oschina.net/zchuanzhao/blog/512560

MySQL for Java的SQL注入测试相关推荐

  1. 怎么进行mysql注入测试_MySQL for Java的SQL注入测试

    只要你学JDBC,基本上所有的人都会和你说,Statement不能防止SQL注入, PreparedStatement能够防止SQL注入. 基本上参加工作了一段时间之后还是这么认为的, 没错, 这句是 ...

  2. SqlMap自动化SQL注入测试工具简绍

    Sqlmap是一个开源的渗透测试工具,可以自动检测和利用SQL注入漏洞并接管数据库服务器.它配备了强大的检测引擎,为终极渗透测试仪提供了许多小众功能,以及从数据库指纹识别,从数据库获取数据到访问底层文 ...

  3. java 防止sql注入_Java中SQL注入以及如何轻松防止它

    java 防止sql注入 什么是SQL注入? (What is SQL Injection?) SQL Injection is one of the top 10 web application v ...

  4. SQL注入测试神器sqlmap

    点击上方蓝字"开源优测"一起玩耍 声明 本公众号所有内容,均属微信公众号: 开源优测  所有,任何媒体.网站或个人未经授权不得转载.链接.转贴或以其他方式复制发布/发表.已经本公众 ...

  5. 如何防范SQL注入 SQL注入测试

    从测试来进行测试SQL注入. 首先,看看SQL注入攻击能分为以下三种类型: Inband: 数据经由SQL代码注入的通道取出,这是最直接的一种攻击,通过SQL注入获取的信息直接反映到应用程序的Web页 ...

  6. golang mysql 防注入_Go,Gorm 和 Mysql 是如何防止 SQL 注入的

    Go,Gorm 和 Mysql 是如何防止 SQL 注入的 SQL 注入和 SQL 预编译技术 什么是 SQL 注入 所谓SQL注入(sql inject),就是通过把SQL命令插入到Web表单提交或 ...

  7. 安全测试中sql注入测试思路

    在找好需要测试的功能点之后,针对每种功能点(参数),sql注入测试一般遵循下面步骤: 1. 测试注入类型,数字型or字符型 如果参数中直接包含字母,那么直接可以判断是字符型参数,如id=4a. 若参数 ...

  8. [Mysql] 防御和检查SQL注入攻击的手段

    SQL注入攻击的种类 知彼知己,方可取胜.首先要清楚SQL注入攻击有哪些种类. 1.没有正确过滤转义字符 在用户的输入没有为转义字符过滤时,就会发生这种形式的注入式攻击,它会被传递给一个SQL语句.这 ...

  9. 安全测试之sql注入测试

    这篇文章,主要是来总结一下,sql注入应该如何去测试. 测试端:数据库服务端 测试点:sql注入 使用工具:burpsuit或Appscan工具或手工或sqlmap 测试方案: 1.使用ibatis或 ...

最新文章

  1. python内置库之学习ctypes库(二)
  2. undefined reference to cv::_InputArray::_InputArray(cv::Mat const)
  3. CTF题目中遇到的PHP考点总结(一)
  4. CentOS经常使用文件操作命令[百度博客搬家]
  5. python命令行tab补全_python命令行下按tab建补全的方法
  6. 我的世界java和基岩版哪个好玩_我的世界:Java版本好玩还是基岩版好玩?老玩家看完后沉默了...
  7. Spring 整合Mybatis Mapper动态代理方法
  8. Expected object of backend CPU but got backend CUDA for argument #4 ‘mat1‘
  9. DataList 编辑记录时,更新取不到值的原因。
  10. cs61a 课时笔记 对象的抽象
  11. php 国际标准时间_时区-如何在PHP中获得格林威治标准时间?
  12. android跑马灯效果不起作用,Android实现跑马灯效果的方法
  13. 转---电脑的MAC实际地址可以修改吗?
  14. 关于安全领域方向上学习的一点个人见解
  15. 模拟量输出模块支持西门子三菱PLC接DCS控制系统
  16. html怎么用空格占位符,HTML空格占位符
  17. 〖Python接口自动化测试实战篇①〗- 自动化测试基础扫盲及项目的生命周期详述
  18. 秒杀系统(SecKillGoods)
  19. 计算机统考木桶效应ppt,木桶效应 课件..ppt
  20. 服务器ras的性能,处理器的RAS性能的重要性

热门文章

  1. php 用户认证,PHP用户认证及管理完全源码
  2. 面向对象程序设计c 语言描述 答案,c面向对象程序设计习题解答全.doc
  3. maven创建Java 和 Web Project, 并导入Eclipse
  4. oracle的一些常见问题及处理
  5. sequelize 外键关联_用Sequelize计算关联条目
  6. rf框架搭建_Robot framework(RF)基本使用
  7. Hie with the Pie(poj3311)
  8. html字段值换行代码怎么写,HTML段落,换行,字符实体
  9. 遇到一个php的错误,php初学者常见的几个错误及解决方法
  10. vue ---- 监听器