Java学习笔记47(JDBCSQL注入攻击原理以及解决)

Posted xuyiqing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java学习笔记47(JDBCSQL注入攻击原理以及解决)相关的知识,希望对你有一定的参考价值。

JDBC:java的数据库连接

JDBC本质是一套API,由开发公司定义的类和接口

这里使用mysql驱动,是一套类库,实现了接口

驱动程序类库,实现接口重写方法,由驱动程序操作数据库

 

JDBC操作步骤:

1.注册驱动

2.获得连接

3.获得语句执行平台

4.执行sql语句

5.处理结果

6.释放资源

 

1.导入jar包,可以在网上下载到,这里使用的是:mysql-connector-java-5.1.37-bin.jar

注册驱动:

package demo;

import java.sql.DriverManager;
import java.sql.SQLException;

import com.mysql.jdbc.Driver;

public class JDBCDemo {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        //注册驱动
        //DriverManager.registerDriver(new Driver());
        //不推荐上边这种方法,建议用反射技术,将驱动类加入内存
        Class.forName("com.mysql.jdbc.Driver");
    }
}

 

2.获得连接:

package demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        //获得数据库连接
        String url = "jdbc:mysql://localhost:3306/mybase";
        String username = "root";
        String password = "xuyiqing";
        Connection con = DriverManager.getConnection(url,username,password);
        System.out.println(con);
    }
}

 

3.获取语句执行平台

通过数据库连接对象,获取到sql语句的执行者对象

package demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mybase";
        String username = "root";
        String password = "xuyiqing";
        Connection con = DriverManager.getConnection(url,username,password);
        //获取语句执行平台
        Statement stat = con.createStatement();
        System.out.println(stat);
    }
}

 

4.执行sql语句:

准备数据:

CREATE TABLE sort(
    sid INT PRIMARY KEY AUTO_INCREMENT,
    sname VARCHAR(100),
    sprice DOUBLE,
    sdesc VARCHAR(5000)
    );
INSERT INTO sort(sname,sprice,sdesc) VALUES(家电,2000,促销),
(家具,8900,价格上涨),
(玩具,300,赚钱),
(生鲜,500.99,促销),
(服装,24000,促销),
(洗涤,50,促销);

SELECT * FROM sort;

 

执行sql语句:

1.增删改

package demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mybase";
        String username = "root";
        String password = "xuyiqing";
        Connection con = DriverManager.getConnection(url,username,password);
        Statement stat = con.createStatement();
        //执行sql语句
        //这种方法注意:只能使用insert,delete,update语句
        int row = stat.executeUpdate("INSERT INTO sort(sname,sprice,sdesc) VALUES(‘汽车‘,2000,‘促销‘);");
        System.out.println(row);
        //释放资源
        stat.close();
        con.close();
    }
}

 

2.查询

package demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mybase";
        String username = "root";
        String password = "xuyiqing";
        Connection con = DriverManager.getConnection(url,username,password);
        Statement stat = con.createStatement();
        //查询sql语句
        String sql= "SELECT * FROM sort"; 
        //这个方法用于执行sql中的select查询
        ResultSet rs = stat.executeQuery(sql);
        //处理结果集
        while(rs.next()){
            //获取每列数据
            System.out.println(rs.getInt("sid")+"   "+rs.getString("sname")+
                    "   "+rs.getDouble("sprice")+"   "+rs.getString("sdesc"));
        }
        rs.close();
        stat.close();
        con.close();
    }
}

输出:

技术分享图片



 

SQL注入攻击简单案例:

CREATE TABLE users(
     id INT PRIMARY KEY AUTO_INCREMENT,
     username VARCHAR(100),
     PASSWORD VARCHAR(100)
);

INSERT INTO users (username,PASSWORD) VALUES (a,1),(b,2);
package demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

/*
 *  Java程序实现用户登录,用户名和密码,数据库检查
 *  演示被别人注入攻击
 */
public class JDBCDemo {
    public static void main(String[] args)throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mybase";
        String username = "root";
        String password = "xuyiqing";
        Connection con = DriverManager.getConnection(url, username, password);
        Statement stat = con.createStatement();
        
        Scanner sc = new Scanner(System.in);
        String user = sc.nextLine();
        String pass = sc.nextLine();
        
        //执行SQL语句,数据表,查询用户名和密码,如果存在,登录成功,不存在登录失败
        String sql = "SELECT * FROM users WHERE username=‘"+user+"‘ AND PASSWORD=‘"+pass+"‘";
        System.out.println(sql);
        ResultSet rs = stat.executeQuery(sql);
        while(rs.next()){
            System.out.println(rs.getString("username")+"   "+rs.getString("password"));
        }
        
        rs.close();
        stat.close();
        con.close();
    }
}

正常情况,必须输入a,1或者b,2才可以登录成功

技术分享图片

这里如果这样输入:
技术分享图片

1=1恒成立,or两边只要有一边成立就会成功,这里就实现了最简单的sql注入攻击

 

 

解决:


使用PrepareStatement接口

package demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

/*
 *  Java程序实现用户登录,用户名和密码,数据库检查
 *  防止注入攻击
 *  Statement接口实现类,作用执行SQL语句,返回结果集
 *  有一个子接口PreparedStatement  (SQL预编译存储,多次高效的执行SQL) 
 *  PreparedStatement的实现类数据库的驱动中,如何获取接口的实现类
 *  
 *  是Connection数据库连接对象的方法
 *  PreparedStatement prepareStatement(String sql) 
          
 */
public class JDBCDemo {
    public static void main(String[] args)throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mybase";
        String username = "root";
        String password = "xuyiqing";
        Connection con = DriverManager.getConnection(url, username, password);
        Scanner sc = new Scanner(System.in);
        String user = sc.nextLine();
        String pass = sc.nextLine();
        
        //执行SQL语句,数据表,查询用户名和密码,如果存在,登录成功,不存在登录失败
        String sql = "SELECT * FROM users WHERE username=? AND PASSWORD=?";
        //调用Connection接口的方法prepareStatement,获取PrepareStatement接口的实现类
        //方法中参数,SQL语句中的参数全部采用问号占位符
        PreparedStatement pst =  con.prepareStatement(sql);
        System.out.println(pst);
        //调用pst对象set方法,设置问号占位符上的参数
        pst.setObject(1, user);
        pst.setObject(2, pass);
        
        //调用方法,执行SQL,获取结果集
        ResultSet rs = pst.executeQuery();
        while(rs.next()){
            System.out.println(rs.getString("username")+"   "+rs.getString("password"));
        }
        
        rs.close();
        pst.close();
        con.close();
    }
}

 

发现这个接口更安全,所以建议使用这个接口实现增删改查

使用PrepareStatement接口,实现数据表的更新操作

package demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

/*
 *  使用PrepareStatement接口,实现数据表的更新操作
 */
public class JDBCDemo {
    public static void main(String[] args) throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mybase";
        String username="root";
        String password="xuyiqing";
        Connection con = DriverManager.getConnection(url, username, password);    
        
        //拼写修改的SQL语句,参数采用?占位
        String sql = "UPDATE sort SET sname=?,sprice=? WHERE sid=?";
        //调用数据库连接对象con的方法prepareStatement获取SQL语句的预编译对象
        PreparedStatement pst = con.prepareStatement(sql);
        //调用pst的方法setXXX设置?占位
        pst.setObject(1, "车");
        pst.setObject(2, 49988);
        pst.setObject(3, 7);
        //调用pst方法执行SQL语句
        pst.executeUpdate();
        
        pst.close();
        con.close();
    }
}

 

 PrepareStatement接口实现数据表的查询操作

package demo;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/*
 *  PrepareStatement接口实现数据表的查询操作
 */
public class JDBCDemo {
    public static void main(String[] args) throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/mybase";
        String username="root";
        String password="xuyiqing";
        Connection con = DriverManager.getConnection(url, username, password);    
        
        String sql = "SELECT * FROM sort";
        
        PreparedStatement pst = con.prepareStatement(sql);
        
        //调用pst对象的方法,执行查询语句,Select
        ResultSet rs=pst.executeQuery();
        while(rs.next()){
            System.out.println(rs.getString("sid")+"  "+rs.getString("sname")+"  "+rs.getString("sprice")+"  "+rs.getString("sdesc"));
        }
        rs.close();
        pst.close();
        con.close();
    }
}

 






以上是关于Java学习笔记47(JDBCSQL注入攻击原理以及解决)的主要内容,如果未能解决你的问题,请参考以下文章

JDBC-03-笔记

《白帽子讲WEB安全》学习笔记之第7章 注入攻击

Web常见安全漏洞原理及防范-学习笔记

《Web安全渗透全套教程(40集)》学习笔记 | SQL注入攻击及防御

试解释 SQL 注入攻击的原理,以及对数据库可能产生的不利影响。

SQL注入学习笔记