日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

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

發布時間:2024/9/20 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 怎么进行mysql注入测试_MySQL for Java的SQL注入测试 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

只要你學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

評論

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的怎么进行mysql注入测试_MySQL for Java的SQL注入测试的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。