SQL注入(案例演示)
阿新 • • 發佈:2021-01-11
SQL注入(案例演示)
一、SQL注入是什麼?
在程式事先定義好的
查詢語句中新增額外的SQL語句
,在管理員不知情的情況下實現非法操作,以此來實現欺騙資料庫伺服器執行非授權的任意查詢
,從而進一步得到相應的資料資訊。
SQL注入通俗說就是:
通過SQL語句找到破綻,進行非法的資料讀取。
二、實現步驟
說明:用一個簡單的查詢案列說明 SQL 注入
案例使用的為:Java語言與MySQL資料庫
1.新建資料表
1.新建一個數據表並新增幾條資料
# 新建表
CREATE TABLE `user` (
`user_name` varchar(255),
`password` varchar(255)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# 向表中新增資料
INSERT INTO `user` VALUES ('zhangsan', '123456');
INSERT INTO `user` VALUES ('1', '2');
INSERT INTO `user` VALUES ('1', '1');
INSERT INTO `user` VALUES ('1', '3');
此時資料庫的資料為下圖所示:
2.SQL注入分析
1.定義SQL語句
可以看出在引數userName和password 的部分SQL語句是傳遞的字串,也就是說可以傳遞任意內容
String sql = "select * from user where user_name = ’ " + userName + "’ and password = ’ " + password + " ’ ";
2.設定userName和password引數值
通過引數userName的傳值來演示獲取非法資料
將userName的值分為四種情況,password 的值在這四種情況下都為固定值 1
合法引數獲取資料 |
---|
String userName = “1”; String password = “1”; |
傳遞引數後SQL語句變為: select * from user where user_name = ‘1’ and password = ‘1’ |
此時可從資料庫中讀取出一條資料: |
非法引數獲取資料(1)—— 掌握一部分資訊即可獲取到其它資訊 |
---|
String userName = “1’ or password = '”; String password = “1”; |
傳遞引數後SQL語句變為: select * from user where user_name = ‘1’ or password = ‘ ' and password = '1 ’ |
此時可從資料庫中讀取出三條資料: |
非法引數獲取資料(2)—— 什麼都不需要即可獲取所有資訊 |
---|
String userName = “’ or user_name like ‘%%’ or password = '”; String password = “1”; |
傳遞引數後SQL語句變為: select * from user where user_name = ‘’ or user_name like ‘%%’ or password = ‘ 'and password = '1 ’ |
此時可從資料庫中讀取出四條資料: |
非法引數獲取資料(3)—— 利用# 註釋掉多餘SQL |
---|
String userName = "’ or user_name like ‘%%’ # or password = ’ "; String password = “1”; |
傳遞引數後SQL語句變為: select * from user where user_name = '' or user_name like '%%' # |
此時可從資料庫中讀取出四條資料: |
3.程式碼案例
1.新建一個User實體類
【說明】
如果不使用lombok的@Data註解,需要新增set get方法和toString方法
@Data
public class User {
private String userName;
private String password;
}
2.新建Demo類,體驗SQL注入
public class Demo {
public static void main(String[] args) throws Exception{
// String userName = "1"; // 正常操作
// String userName = "1' or password = '"; // 掌握丟丟資訊就可以獲取其它資訊
// String userName = "' or user_name like '%%' or password = '"; // 什麼都不需要就可拿到所有資訊
String userName = "' or user_name like '%%' # or password = ' "; // 升級版
String password = "1";
// 載入資料庫驅動
Class.forName("com.mysql.jdbc.Driver");
// 建立資料庫連線
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/user表所在的資料庫名?" +
"characterEncoding=utf-8&useUnicode=true","root","123456");
// 定義SQL語句
String sql = "select * from user where user_name = '" + userName + "' and password = '" + password + "'";
// 打印出拼接後的SQL語句
System.out.println(sql);
// 建立SQL執行物件
Statement stmt = conn.createStatement();
// 執行SQL語句並返回結果集
ResultSet rs = stmt.executeQuery(sql);
// 遍歷出結果集到List集合
List<User> userList = new CopyOnWriteArrayList<>();
while (rs.next()) {
User user = new User();
user.setUserName(rs.getString(1));
user.setPassword(rs.getString(2));
userList.add(user);
}
// 列印結果集
for (User user : userList) {
System.out.println(user);
}
}
}
三、防止SQL注入的方式
- SQL預編譯(Java提供了PreparedStatement類)
- 校驗引數(使用正則表示式等)