1 -【 常見 web 安全漏洞 】- 2 SQL 注入攻擊

Fork me on Gitee

0 環境準備

1 數據庫環境準備

-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `userName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES (1, 'yang', '123456');

2 依賴

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.6.RELEASE</version>
    <relativePath/>
</parent>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <!-- SpringBoot web 核心組件 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <!-- mysql 數據庫驅動. -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!-- spring-boot mybatis依賴 -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>1.3.2</version>
    </dependency>
    <!-- SpringBoot 對lombok 支持 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.6</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

3 配置文件

spring:
  datasource:
    url: jdbc:mysql://120.78.134.111:3306/springboot?useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
mybatis:
  type-aliases-package: com.snow.entity # mybatis 別名掃描

5 啓動項

package com.snow;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.snow.mapper")
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

}

6 實體類

package com.snow.entity;

import lombok.Data;
import lombok.ToString;

/**
 * @author :yang-windows
 * @Title : springboot
 * @Package :com.snow.entity
 * @Description : User
 * @date :2020/4/16 11:44
 */
@Data
@ToString
public class User {

    private Long id;
    private String userName;
    private String password;

}

7 UserMapper

package com.snow.mapper;

import com.snow.entity.User;
import org.apache.ibatis.annotations.Select;

/**
 * @author :yang-windows
 * @Title : springboot
 * @Package :com.snow.mapper
 * @Description : UserMapper
 * @date :2020/4/16 11:46
 */
public interface UserMapper {

    @Select("SELECT * FROM user_info WHERE userName=#{userName} AND password=#{password}")
    public User login(User user);

}

8 controller

package com.snow.controller;

import com.snow.entity.User;
import com.snow.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author :yang-windows
 * @Title : springboot
 * @Package :com.snow.controller
 * @Description : LoginController
 * @date :2020/4/8 22:25
 */
@RestController
public class LoginController {

    @Autowired
    private UserMapper userMapper;

    @RequestMapping("/login")
    public String login(User user) {
        System.out.println("賬號密碼信息:user:" + user.toString());
        User login = userMapper.login(user);
        return login == null ? "登陸失敗!" : "登陸成功!";
    }

}

9 測試

啓動項目,瀏覽器訪問:http://127.0.0.1:8080/login?userName=yang&password=123456

在這裏插入圖片描述

1 什麼是 SQL 注入

SQL 注入:利用現有應用程序,將(惡意)的 SQL 命令注入到後臺數據庫執行一些惡意的代碼。

造成 SQL 注入的原因是因爲程序沒有有效過濾用戶的輸入,使攻擊者成功的向服務器提交惡意的 SQL 查詢代碼,程序在接收後錯誤的將攻擊者的輸入作爲查詢語句的一部分執行,導致原始的查詢邏輯被改變,額外的執行了攻擊者精心構造的惡意代碼。

2 演示 SQL 注入攻擊

修改 UserMapper

package com.snow.mapper;

import com.snow.entity.UserEntity;
import org.apache.ibatis.annotations.Select;

public interface UserMapper {

    @Select("SELECT * FROM user_info WHERE userName=${userName} AND password=${password}")
    public UserEntity login(UserEntity userEntity);

}

在這裏插入圖片描述

啓動項目,瀏覽器輸入:http://127.0.0.1:8080/login?userName=yang&password=123456

報錯:
在這裏插入圖片描述

查看日誌:

### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Unknown column 'yang' in 'where clause'
### The error may exist in com/snow/mapper/UserMapper.java (best guess)
### The error may involve com.snow.mapper.UserMapper.login-Inline
### The error occurred while setting parameters
### SQL: SELECT * FROM user_info WHERE userName=yang AND password=123456
### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'yang' in 'where clause'
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Unknown column 'yang' in 'where clause'] with root cause

java.sql.SQLSyntaxErrorException: Unknown column 'yang' in 'where clause'
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[mysql-connector-java-8.0.19.jar:8.0.19]
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) ~[mysql-connector-java-8.0.19.jar:8.0.19]
	

原因:$ 是字符串拼接,所以查詢時字段爲 varchar 時,需要添加 '

package com.snow.mapper;

import com.snow.entity.User;
import org.apache.ibatis.annotations.Select;

/**
 * @author :yang-windows
 * @Title : springboot
 * @Package :com.snow.mapper
 * @Description : UserMapper
 * @date :2020/4/16 11:46
 */
public interface UserMapper {

    @Select("SELECT * FROM user_info WHERE userName='${userName}' AND password='${password}'")
    public User login(User user);

}

在這裏插入圖片描述

再次測試,瀏覽器輸入:http://127.0.0.1:8080/login?userName=yang&password=123456

在這裏插入圖片描述

演示 SQL 注入攻擊

啓動項目,瀏覽器訪問:http://127.0.0.1:8080/login?userName=yang&password=123456’or’1’='1

在這裏插入圖片描述

爲什麼瀏覽器訪問地址會變成:

http://127.0.0.1:8080/login?userName=yang&password=123456%27or%271%27=%271

這是因爲瀏覽器會將特殊的字符進行轉碼。

3 防止 SQL 注入攻擊手段

不要使用拼接 SQL 語句方式、最好使用預編譯方式,在 mybatis 編寫 sql 語句的時候,最好使用 ? 傳參數方式,不要使用 $ 傳參數,因爲 $ 傳參數方式,可能會受到 sql 語句攻擊。

package com.snow.mapper;

import com.snow.entity.User;
import org.apache.ibatis.annotations.Select;

/**
 * @author :yang-windows
 * @Title : springboot
 * @Package :com.snow.mapper
 * @Description : UserMapper
 * @date :2020/4/16 11:46
 */
public interface UserMapper {

    @Select("SELECT * FROM user_info WHERE userName=#{userName} AND password=#{password}")
    public User login(User user);

}

在這裏插入圖片描述

4 MyBatis #$ 區別

  • #{}:解析爲一個 JDBC 預編譯語句(prepared statement)的參數標記符,一個 #{ } 被解析爲一個參數佔位符,可以防止 SQL 注入問題。

  • ${}:僅僅爲一個純碎的 string 替換,在動態 SQL 解析階段將會進行變量替換。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章