只要你学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);
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;
}
}
"jdbc:mysql://localhost:3306/java_mysql";
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
jdbc:mysql://localhost:3306/java_mysql?allowMultiQueries=true
select id, name, age from pstest where name ='Tom';delete from pstest;select * from pstest where name='Tom';
上面的SQL到底做了什么呢?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> 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查询, 没有查询到任何数据
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();
}
}
}
[mysqld]
log=MySQL_Log # 在这里加上日志名称
这时候会在MySQL/MySQL Server 5.1/Data/目录下生成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
select id, name, age from pstest where name = 'Tom\';delete from pstest;select * from pstest where name=\'Tom'
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)
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");
// 以下代码省略...
}
}
505



被折叠的 条评论
为什么被折叠?



