一、老生常談的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 |
最後,如果對文章有什麼疑問或者問題,歡迎留言