一、老生常谈的SQL注入如何实现
估计大部分都知道方法:任意内容 ’ or 永真语句 注释符,这种方式实现。通过or表示或,与永为真语句搭配保持前面部分永远真,然后用注释符屏蔽掉后面实现条件永为真的操作。
二、为什么通过占位符方式可以避免SQL注入
打Java操作数据库的例子来说。
Java通过PreparedStatement类执行SQL语句时,SQL语句中变量用?来代替,之后对SQL语句进行预编译。PreparedStatement再调用set方式传入下标和变量进行赋值,再执行SQL语句。这期间,SQL预编译后下次传进来的内容,直接针对这些内容操作就好。比如
select * from user where name = ? and pwd=?
这先把sql语句编译,之后执行。就算传入例如:name:abc‘ or 1=1 #,pwd:111,也会把“abc‘ or 1=1 #”单独当做一个name值进行匹配。结果就是匹配不到,防止了SQL注入。
三、MySQL中的注释符(#和–的区别)
MySQL中注释有两种方式:
①#注释内容
②-- 注释内容(注意–后面与注释内容之间要有空格)
下面用四张sql注入试验结果,表名两种注释加与不加空格结果
从上面四幅图看出,sql注入时,#后面加与不加空格都成功了。而在使用–时,–后面必须加空格才生效,不加空格个则会被检查出语法错误。
四、附上此文章中用到的代码和数据库表
代码部分可到main函数去放掉对应方法的注释,另外代码开头部分的数据库也要根据个人数据库进行修改,我的数据库是5.5版本的MySQL,url中test是我存放之后数据库表对应的库名,user和password请根据个人连接数据库用到的名字和密码进行修改的。如果是普通Java项目,还需要到网上下载对应的数据库驱动jar包,并应用到当前项目。
package JdbcDemo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class jdbcdemo {
static Connection connection;
static Statement statement;
static PreparedStatement preparedStatement;
private static final String driver = "com.mysql.jdbc.Driver";
private static final String url = "jdbc:mysql://localhost:3306/test";
private static final String user = "root";
private static final String password = "318523";
//数据库操作练习
public static void OperateDatabase() {
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, user, password);
if (!connection.isClosed()) {
System.out.println("Database connection success.");
// statement=connection.createStatement();
// String name="xiaojun";
// int age=40;
// String sql = "insert into student(name,age) values('"+name+"','"+age+"') ";
// int count = statement.executeUpdate(sql);
String sql = "insert into student values(?,?) ";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "xiaohong");
preparedStatement.setInt(2, 19);
int count = preparedStatement.executeUpdate();
if (count > 0) {
System.out.println("insert success.");
}
} else {
System.out.println("Database connection failed.");
return;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (preparedStatement != null) preparedStatement.close();
if (statement != null) statement.close();
if (connection != null) connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//sql注入,Statement类执行测试
public static void SQLInjectStatement() {
ResultSet resultSet=null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, user, password);
if (!connection.isClosed()) {
System.out.println("Database connection success.");
Statement statement = connection.createStatement();
String name;
String pwd;
Scanner scanner = new Scanner(System.in);
System.out.println("input name:");
name = scanner.nextLine();
System.out.println("input pwd");
pwd = scanner.nextLine();
String sql = "select * from user where name ='"+name+"'and pwd ='"+pwd+"'";
resultSet = statement.executeQuery(sql);
if(resultSet.next()){
System.out.println("Login successfully!");
}else {
System.out.println("Login failed.");
}
} else {
System.out.println("Database connection failed.");
return;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(resultSet!=null) resultSet.close();
if (statement != null) statement.close();
if (connection != null) connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//sql注入,PrepareStatement执行测试
public static void SQLInjectPrepareStatement() {
ResultSet resultSet=null;
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, user, password);
if (!connection.isClosed()) {
System.out.println("Database connection success.");
String sql = "select * from user where name =? and pwd =?";
preparedStatement = connection.prepareStatement(sql);
String name;
String pwd;
Scanner scanner = new Scanner(System.in);
System.out.println("input name:");
name = scanner.nextLine();
System.out.println("input pwd");
pwd = scanner.nextLine();
preparedStatement.setString(1,name);
preparedStatement.setString(2,pwd);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()){
System.out.println("Login successfully!");
}else {
System.out.println("Login failed.");
}
} else {
System.out.println("Database connection failed.");
return;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if(resultSet!=null) resultSet.close();
if (statement != null) statement.close();
if (connection != null) connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//OperateDatabase();
//SQLInjectStatement();
SQLInjectPrepareStatement();
return;
}
}
用到的数据库表,为了测试比较简单
student表
Field | Type | Null | Key | Default | Extra |
---|---|---|---|---|---|
name | varchar(10) | YES | NULL | ||
age | tinyint(4) | YES | NULL |
user表
Field | Type | Null | Key | Default | Extra |
---|---|---|---|---|---|
name | varchar(10) | YES | NULL | ||
pwd | varchar(10) | YES | NULL |
最后,如果对文章有什么疑问或者问题,欢迎留言