只要你学JDBC,基本上所有的人都会和你说,Statement不能防止SQL注入, PreparedStatement能够防止SQL注入.

基本上参加工作了一段时间之后还是这么认为的, 没错, 这句是没有问题的, 但到底如何进行SQL注入?怎么直观的去了解SQL注入?这还是需要花一定的时间去实验的.

前提:以下的测试都是在一种理想环境下

首先准备好数据库环境, 以下是数据库的schema:

create database java_mysql;

use java_mysql;

drop table if exists pstest;

create table pstest(

id int(10) not null primary key auto_increment,

name varchar(32),

age int(3)

);

insert into pstest (name, age) values ('Tom', 23);

insert into pstest (name, age) values ('Tom1', 23);

insert into pstest (name, age) values ('Tom2', 23);

insert into pstest (name, age) values ('Tom3', 23);

insert into pstest (name, age) values ('Tom4', 23);

insert into pstest (name, age) values ('Tom5', 23);

以上就是建立了pstest表, 并插入了一些测试数据.

1. 测试Statement

public class StatementTest {

public static void main(String[] args) throws SQLException {

Connection con = null;

Statement stmt = null;

// name很强大, 传入了这么多东西

String name = "Tom';delete from pstest;select * from pstest where name='Tom";

String sql = createSql(name); // SQL

System.out.println(sql);

try {

con = DBConn.getConnection();

stmt = con.createStatement();

stmt.execute(sql);

} catch(Exception e) {

e.printStackTrace();

} finally {

stmt.close();

con.close();

}

}

// 根据参数的name参数查询

private static String createSql(String name) {

String sql = "select id, name, age from pstest ";

// 拼接一下SQL

if(name != null && name.length() != 0) {

sql += "where name ='" + name + "'";

}

return sql;

}

}

数据库连接的URL为:

"jdbc:mysql://localhost:3306/java_mysql";

其实上面的意图很简单:

Tom';delete from pstest;select * from pstest where name='Tom

就是想先执行一条SQL查询语句,然后把表的数据删除。

这只是理想环境. 实际上要想传入这么复杂的数据, 真的很难想象

这里将URL单独拎出来是有作用的, 继续看下面

Run一下StatementTest. 会发现报异常了:

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:

jdbc:mysql://localhost:3306/java_mysql?allowMultiQueries=true

重点是allowMultiQueries=true这个参数

再来Run一下StatementTest. OK,没有报任何的异常.打印的SQL为:

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条数据

mysql> select * from pstest;

+----+------+------+

| id | name | age |

+----+------+------+

| 1 | Tom | 23 |

| 2 | Tom1 | 23 |

| 3 | Tom2 | 23 |

| 4 | Tom3 | 23 |

| 5 | Tom4 | 23 |

| 6 | Tom5 | 23 |

+----+------+------+

执行一下

select id, name, age from pstest where name ='Tom';delete from pstest;select * from pstest where name='Tom';

这时候可以看到MySQL客户端

mysql> select id, name, age from pstest where name ='Tom';delete from pstest;select * from pstest where name='Tom';

+----+------+------+

| id | name | age |

+----+------+------+

| 1 | Tom | 23 |

+----+------+------+

1 row in set (0.00 sec) -- 执行第一条查询SQL

Query OK, 6 rows affected (0.05 sec) -- 执行第二条delete语句, Oh, No, 数据库全部的6条数据被删除了

Empty set (0.00 sec) -- 执行第三条SQL查询, 没有查询到任何数据

上面的注释已经写好了,就不多说了。

这时候的确已经实现了SQL注入.

2. 测试PreparedStatemet

public class PreparedStatementTest {

public static void main(String[] args) throws SQLException {

Connection con = null;

PreparedStatement ps = null;

ResultSet rs = null;

String sql = "select id, name, age from pstest where name = ? ";

try {

con = DBConn.getConnection();

ps = con.prepareStatement(sql);

ps.setString(1, "Tom';delete from pstest;select * from pstest where name='Tom");

rs = ps.executeQuery();

} catch(Exception e) {

e.printStackTrace();

} finally {

rs.close();

ps.close();

con.close();

}

}

}

直接Run一下,OK,也没出现任何的异常,数据库中的数据也还在

但是我们到底执行了什么样的SQL, 查看MySQL的日志.

这里简单提下MySQL的日志,可以在my.ini下配置

[mysqld]

log=MySQL_Log # 在这里加上日志名称

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

好了,回到正题,看一下刚刚PreparedStatementTest执行的SQL,在MySQL_Log中查看

120719 15:54:25 23 Connect root@localhost on java_mysql

23 Query /* mysql-connector-java-5.1.20-SNAPSHOT ( Revision: ${bzr.revision-id} ) ...

23 Query SHOW WARNINGS

23 Query /* mysql-connector-java-5.1.20-SNAPSHOT ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increment_increment

23 Query SHOW COLLATION

23 Query SET character_set_results = NULL

23 Query SET autocommit=1

23 Query select id, name, age from pstest where name = 'Tom\';delete from pstest;select * from pstest where name=\'Tom'

23 Quit

重点是最后一条SQL.

因为数据库中的数据都还在,我们就直接执行这条SQL

select id, name, age from pstest where name = 'Tom\';delete from pstest;select * from pstest where name=\'Tom'

查看MySQL的客户端

mysql> select id, name, age from pstest where name = 'Tom\';delete from pstest;select * from pstest where name=\'Tom';

Empty set (0.00 sec) -- 就执行了这一条查询的SQL语句

可以看到什么的字符串已经被转义了.

让我们来看一下转义字符:

mysql> select 'Tom\';delete';

+-------------+

| Tom';delete |

+-------------+

| Tom';delete |

+-------------+

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类:

public class ResultSetRegressionTest extends BaseTestCase {

public void testBug33678() throws Exception {

if (!versionMeetsMinimum(4, 1)) {

return;

}

createTable("testBug33678", "(field1 INT)");

// allowMultiQueries=true设置

Connection multiConn = getConnectionWithProps("allowMultiQueries=true");

Statement multiStmt = multiConn.createStatement();

try {

multiStmt.setFetchSize(Integer.MIN_VALUE);

// 一次性执行多条SQL语句

multiStmt

.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");

// 以下代码省略...

}

}

2

0

分享到:

2012-07-19 17:30

浏览 8235

评论

怎么进行mysql注入测试_MySQL for Java的SQL注入测试相关推荐

  1. MySQL for Java的SQL注入测试

    2019独角兽企业重金招聘Python工程师标准>>> 只要你学JDBC,基本上所有的人都会和你说,Statement不能防止SQL注入, PreparedStatement能够防止 ...

  2. mysql 注入用例_SQL注入漏洞安全测试(WVS/POST型/手工SQL注入)

    1.WVS自动化SQL注入测试 n  测试目的: 测试网站是否存在SQL注入漏洞. n  测试用例: 1)     Scan settings选择sql injection策略: 2)     输入扫 ...

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

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

  4. 网络渗透测试实验三——XSS和SQL注入

    网络渗透测试实验三--XSS和SQL注入 实验目的 了解什么是XSS:了解XSS攻击实施,理解防御XSS攻击的方法:了解SQL注入的基本原理:掌握PHP脚本访问MySQL数据库的基本方法:掌握程序设计 ...

  5. php mysql 注入一句话木马_渗透技术--SQL注入写一句话木马原理

    讲一下SQL注入中写一句话拿webshell的原理,主要使用的是 SELECT ... INTO OUTFILE 这个语句,下面是一个语句的例子: SELECT * INTO OUTFILE 'C:\ ...

  6. mysql注入漏洞语句,web安全之sql注入漏洞

    概念 通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.通俗地讲,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力 ...

  7. 如何测试WEB应用程序防止SQL注入***

    摘要: 在WEB应用程序的软件测试中,安全测试是非常重要的一部分,但常常容易被忽视掉.在安全测试中,防止SQL注入***尤其重要.本文介绍了SQL注入***产生的后果以及如何进行测试. 关键字:安全测 ...

  8. SQL注入是什么,怎么防止SQL注入?

    SQL注入是什么,怎么防止SQL注入? 一.什么是SQL注入? SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录 ...

  9. php如何防sql注入,如何在PHP中防止SQL注入

    本篇文章将给大家介绍关于PHP中的SQL注入以及使用PHP-MySQLi和PHP-PDO驱动程序防止SQL注入的方法.下面我们来看具体的内容. 简单的SQL注入示例 例如,A有一个银行网站.已为银行客 ...

最新文章

  1. 如何找回由于IO设备错误移动磁盘的文件
  2. 小程序确定取消弹窗_微信小程序定制开发价格确定条件?
  3. jQuery.ajax实现根据不同的Content-Type做出不同的响应
  4. linux 隐藏显示终端光标
  5. 中琛物联‘连接+云+数据’服务助阵
  6. python连接hive kerberos_数据库开发实战教程:使用Python连接Kerberos的Presto
  7. 虎年继续做朋友,再来认识一下云和恩墨
  8. 算法资料:算法导论_原书第3版(中文)(PDF带书签)
  9. office软件不显示图标
  10. Edge工程师:我在微软300+天,谈谈我眼中的微软
  11. Nexus 5刷阿里云OS
  12. 时空大数据解决方案-最新全套文件
  13. CRP原理的简单例子
  14. 《统计之美:人工智能时代的科学思维》(李舰,海恩)读书记录 - 1
  15. 操作系统文件管理实验
  16. Spring事务问题
  17. 202112-3登机牌条码(40分骗分)
  18. 涂子沛:个人信息保护入法,堵住非法变现通道
  19. FLASH分区图及ROM固件提取、修改及打包
  20. 轻松白嫖几十T硬盘空间,阿里云盘转本地硬盘小工具分享~

热门文章

  1. C++volatile
  2. QT的QSignalTransition类的使用
  3. QT的QMimeDatabase类的使用
  4. C++指针地址内存,数据结构,文件操控
  5. word2vec原理_深入理解Word2Vec底层原理
  6. c++ 获取linux系统信息_linux系统c程序移植
  7. c语言用hash方式数组去重,js数组去重的hash方法
  8. 12_VersionedCollapsingMergeTree,Log Engine Family(Log引擎,StripeLog引擎,TinyLog引擎)
  9. 31-32 python mysql-connector创建数据、crud,where,排序,删除等。PyMSQL驱动,插入操作、查询操作、更新操作、删除操作、执行
  10. nginx配置中proxy_redirect的作用(转)