Java最新SQL注入原因以及預防方案(易理解)

2021-01-11 51CTO

 前沿

在現有的框架中sql防注入已經做得很好了,我們需要做的就是儘量不要使用sql拼接調用

java sql注入原因以及預防方案(易理解)

1. SQL注入

1.1 原理

SQL注入是通過客戶端的輸入把SQL命令注入到一個應用的資料庫中,從而執行惡意的SQL語句。

1.2 演示

1.2.1 案例1

有一個登錄框,需要 輸入用戶名和密碼 ,然後我們的密碼輸入 'or '123' = '123 這樣的。我們在查詢用戶名和密碼是否正確的時候,本來執行的sql語句是:select * from user where username = '' and password = ''. 這樣的sql語句,現在我們輸入密碼是如上這樣的,然後我們會通過參數進行拼接,拼接後的sql語句就是:

select * from user where username = '' and password = ' ' or '123' = '123 ';這樣的了,那麼會有一個or語句,只要這兩個有一個是正確的話,就條件成立,因此 123 = 123 是成立的。因此驗證就會被跳過。這只是一個簡單的例子,

1.2.2 案例2

密碼比如是這樣的:'; drop table user;, 這樣的話,那麼sql命令就變成了:

select * from user where username = '' and password = ''; drop table user;', 那麼這個時候我們會把user表直接刪除了。

1.3 防範

1.3.1 前端

前端表單進行參數格式控制;

1.3.2 後端

我們可以使用預編譯語句(PreparedStatement,這 樣的話即使我們使用sql語句偽造成參數,到了服務端的時候,這個偽造sql語句的參數也只是簡單的字符,並不能起到攻擊的作用。 使用正則表達式過濾傳入的參數

注意: 永遠也不要把未經檢查的用戶輸入的值直接傳給資料庫

package cn.javanode.thread;  import java.util.regex.Pattern;  /**  * @author xgt(小光頭)  * @version 1.0  * @date 2021-1-8 11:48  */ public class CheckSqlDemo {      /**正則表達式**/     private static String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"             + "(\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";       private static Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);      private static boolean isValid(String str) {         if (sqlPattern.matcher(str).find())         {             System.out.println("未能通過過濾器:str=" + str);             return false;         }         return true;     }      public static void main(String[] args) {         System.out.println(isValid("tongji_user_add"));     }  } 

補充

PreparedStatement是如何防止SQL注入的?

1. 拼接參數(sql注入)

Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);         PreparedStatement preparedStatement = connection.prepareStatement(sql);                 String param = "'test' or 1=1";         String sql = "select file from file where name = " + param; // 拼接SQL參數         ResultSet resultSet = preparedStatement.executeQuery();         System.out.println(resultSet.next()); 

輸出結果為 true ,DB中執行的SQL為

 select file from file where name = 'test' or 1=1 

2. setString (防注入)

Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);         PreparedStatement preparedStatement = connection.prepareStatement(sql);             preparedStatement.setString(1,account);//設置參數         preparedStatement.setString(2,password);         ResultSet resultSet = preparedStatement.executeQuery();//執行查詢sql,獲取結果集 

輸出結果為 false ,DB中執行的SQL為

select file from file where name = '\'test\' or 1=1' 

我們可以看到輸出的 SQL是把整個參數用引號包起來,並把參數中的引號作為轉義字符,從而避免了參數也作為條件的一部分

3. 源碼分析

結論

preparedStatement.setString 會判斷當前參數的符號是否需要轉義,是的話加的轉義符 如果不需要,則直接加上引號

//完整代碼 public void setString(int parameterIndex, String x) throws SQLException {        synchronized (checkClosed().getConnectionMutex()) {            // if the passed string is null, then set this column to null            if (x == null) {                setNull(parameterIndex, Types.CHAR);            } else {                checkClosed();                 int stringLength = x.length();                 if (this.connection.isNoBackslashEscapesSet()) {                    // Scan for any nasty chars                    // 判斷是否需要轉義                    boolean needsHexEscape = isEscapeNeededForString(x, stringLength);                     if (!needsHexEscape) {                        byte[] parameterAsBytes = null;                         StringBuilder quotedString = new StringBuilder(x.length() + 2);                        quotedString.append('\'');                        quotedString.append(x);                        quotedString.append('\'');                         if (!this.isLoadDataQuery) {                            parameterAsBytes = StringUtils.getBytes(quotedString.toString(), this.charConverter, this.charEncoding,                                    this.connection.getServerCharset(), this.connection.parserKnowsUnicode(), getExceptionInterceptor());                        } else {                            // Send with platform character encoding                            parameterAsBytes = StringUtils.getBytes(quotedString.toString());                        }                         setInternal(parameterIndex, parameterAsBytes);                    } else {                        byte[] parameterAsBytes = null;                         if (!this.isLoadDataQuery) {                            parameterAsBytes = StringUtils.getBytes(x, this.charConverter, this.charEncoding, this.connection.getServerCharset(),                                    this.connection.parserKnowsUnicode(), getExceptionInterceptor());                        } else {                            // Send with platform character encoding                            parameterAsBytes = StringUtils.getBytes(x);                        }                         setBytes(parameterIndex, parameterAsBytes);                    }                     return;                } 

【編輯推薦】

【責任編輯:

姜華

TEL:(010)68476606】

點讚 0

相關焦點

  • 安全漏洞XSS、CSRF、SQL注入以及DDOS攻擊
    安全漏洞XSS、CSRF、SQL注入以及DDOS攻擊 隨著網際網路的普及,網絡安全變得越來越重要,程式設計師需要掌握最基本的web安全防範,下面列舉一些常見的安全漏洞和對應的防禦措施。
  • SQL注入、XSS以及CSRF分別是什麼?
    什麼是SQL注入、XSS和CSRF?本篇文章就來帶大家了解一下SQL注入、XSS和CSRF,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。SQL注入SQL注入是屬於注入式攻擊,這種攻擊是因為在項目中沒有將代碼與數據(比如用戶敏感數據)隔離,在讀取數據的時候,錯誤的將數據作為代碼的一部分執行而導致的。典型的例子就是當對SQL語句進行字符串拼接的時候,直接使用未轉義的用戶輸入內容作為變量。這時,只要在sql語句的中間做修改,比如加上drop、delete等關鍵字,執行之後後果不堪設想。
  • 最詳細的SQL注入相關的命令整理
    Readline',@out out insert INTO MYTMP(info) VALUES (@out) EXEC sp_oagetproperty @file,'AtEndOfStream',@isEnd out IF @isEnd=1 BREAK ELSE CONTINUE END(3)首先開啟jet沙盤模式,通過擴展存儲過程 xp_regwrite修改註冊表實現,管理員修改註冊表不能預防的原因
  • Java中加載資料庫驅動的方式有幾種?背後的原理是什麼?
    Driver接口先來了解下java.sql.Driver接口,java.sql.Driver是所有JDBC驅動程序需要實現的接口。這個接口是提供給資料庫廠商使用的,不同廠商實現該接口的類名是不同的,例如MySQL 8.x的JDBC驅動的類名是:com.mysql.cj.jdbc.Driver。
  • SQL注入是什麼?如何防止?
    SQL注入是一種注入攻擊,可以執行惡意SQL語句。下面本篇文章就來帶大家了解一下SQL注入,簡單介紹一下防止SQL注入攻擊的方法,希望對大家有所幫助。什麼是SQL注入?SQL注入(SQLi)是一種注入攻擊,,可以執行惡意SQL語句。它通過將任意SQL代碼插入資料庫查詢,使攻擊者能夠完全控制Web應用程式後面的資料庫伺服器。
  • JAVA專業術語面試100問
    29、簡述java內存分配與回收策率以及Minor GC和Major GC?30、JVM,JDK和JRE有什麼區別與聯繫?31、Java線程同步的方式有哪些?32、解釋一下鎖的一些基本概念:可重入鎖、可中斷鎖、公平鎖、讀寫鎖?
  • 開發崗位這麼多,為什麼選Java?你學Java了嗎-開課吧
    零基礎學Java主流開發語言根據最新2020年提到C++語言,很多人發現在使用過程中最容易出現的錯誤就是內存管理,而java有自動垃圾回收器,不用擔心內存。零基礎學Java作為一門面向對象的高級語言,Java不僅吸收了C++語言的各種優點,還對C++裡諸如多繼承、指針等一些讓用戶難以理解和掌握的概念重新組織和及摒棄
  • Java編程領域你需要懂得技術名詞解釋與常用開源框架理解
    IoC(DI)依賴注入實現的技術:反射機制、工廠模式。是方法級別的攔截,攔截到方法後根據參數上的註解,把request數據注入進去。一個方法對應一個Request上下文,所以方法直接基本上是獨立的,獨享request,response數據。、開發效率對比:由於SpringMVC基於方法的攔截,有加載一次單例模式bean注入。
  • 為什麼不推薦使用try-catch-finally處理java異常?
    這篇文章是我近期看了《Effective java》一書中總結的,來自其中第九條。為了對其理解的更加透徹,因此重新分析了一下,並加入了一些其他點。「本文的所有例子均在本地代碼運行完畢基於JDK版本1.8,運行環境eclipse本文類名:TryWithResources,下文的堆棧信息也以此為基礎」在java開發中,一些網絡連結或者是文件資源都需要程式設計師去手動調用close方法關閉,比如InputStream、OutputStream和java.sql.Connection
  • 遠程連接不上SQL資料庫6大可能的問題原因列舉
    打開APP 遠程連接不上SQL資料庫6大可能的問題原因列舉 發表於 2018-10-27 09:31:40 聲明:如果連接不上請參照以下步驟排查(這個是百度出來的最有可能碰到的情況,因為SQL是微軟體的產品不是本公司的軟體,涉及到比較複雜的操作步驟筆者也不是非常擅長,還請理解!
  • 使用exp進行SQL報錯注入 - 51CTO.COM
    mysql> select exp(2.70805020110221);+---+| exp(2.70805020110221) |+---+|                    15 |+---+1 row in set (0.00 sec)0x02 注入
  • PandaSQL:一個讓你能夠通過SQL語句進行pandas的操作的python包
    我們可以通過聯接項目列以及聯接條件(TransactionDt≥StartDt和TransactionDt≤EndDt)來實現這一點。因為現在我們的連接條件也有大於號和小於號,這樣的連接稱為不等連接。在繼續之前,一定要考慮如何在pandas中做這樣的事情。pandas的解決方案那麼在pandas身上該怎麼做呢?
  • 大數據分析工程師入門9-Spark SQL
    比如:使用sql-需要sqlContext,使用hive-需要hiveContext,使用streaming-需要StreamingContext。SparkSession封裝了SparkContext和SQLContext。
  • sqltoy-orm-4.16.11 發版,部分功能優化
    的十四個關鍵特點:1、最簡最直觀的sql編寫方式(不僅僅是查詢語句),採用條件參數前置處理規整法,讓sql語句部分跟客戶端保持高度一致2、sql中支持注釋(規避了對hint特性的影響,知道hint嗎?搜oracle hint),和動態更新加載,便於開發和後期維護整個過程的管理3、支持緩存翻譯和反向緩存條件檢索(通過緩存將名稱匹配成精確的key),實現sql簡化和性能大幅提升4、支持快速分頁和分頁優化功能,實現分頁最高級別的優化,同時還考慮到了cte多個with as情況下的優化支持5、支持並行查詢6、根本杜絕sql注入問題,以後不需要討論這個話題7、支持行列轉換
  • 【大數據】最新大數據學習路線(完整詳細版】
    ,redis)Spark(scala,spark,spark core,spark sql,spark streaming,spark mllib,spark graphx)Python(python,spark python)?
  • (提高Java代碼質量)|25個優化Java代碼的小技巧
    這就是為什麼需要把魔法值定義為可讀取常量的原因。但是,-1、0 和 1 不被視為魔法值。反例:正例:10.不要使用集合實現來賦值靜態成員變量對於集合類型的靜態成員變量,不要使用集合實現來賦值,應該使用靜態代碼塊賦值。
  • java float double精度為什麼會丟失?淺談java的浮點數精度問題
    問題大概情況可以通過如下代碼理解:得到的結果如下:f=2.0015E7d=2.0015E7d2=2.0014999E7從輸出結果可以看出double 可以正確的表示20014999 ,而float 沒有辦法表示20014999 ,得到的只是一個近似值。這樣的結果很讓人訝異。
  • 關於「牙蟲」:談談齲齒形成的原因,以及預防齲齒的根本辦法
    關於「牙蟲」:談談齲齒形成的原因,以及預防齲齒的根本辦法星期天,好友老趙登門造訪,開門見山地說:「老陳,我有一隻牙,喝涼水或吃酸甜的東西都感到酸痛,請你給我看看。」我請他張開嘴巴看了一下,原來是一隻「蛀牙」,已經是牙科醫生所說的「中期齲」了。所謂蛀牙或蟲牙,在醫學上稱為齲齒。