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

2021-01-12 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

相關焦點

  • Sql注入攻擊基本原理
    本文將帶你從介紹 Web 應用運行原理開始,一步一步理解 Sql 注入的由來、原理和攻擊方式。3、Sql注入產生原因及威脅剛剛講過當我們訪問動態網頁時, Web 伺服器會向數據訪問層發起 Sql 查詢請求,如果權限驗證通過就會執行 Sql 語句。
  • Java資料庫連接性簡介
    JDBC導入importjava.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;import java.sql.ResultSet;import java.sql.
  • JAVA-新手入門:JAVA資料庫基本操作指南
    java 資料庫基本操作  1、java資料庫操作基本流程  2、幾個常用的重要技巧:  ·可滾動、更新的記錄集  ·批量更新  ·事務處理java資料庫操作基本流程:取得資料庫連接 - 執行sql語句 - 處理執行結果 - 釋放資料庫連接基礎視頻有挺多的你是看你的學習欲望!!!!
  • Java資料庫類的原型
    這是調用DB類的代碼: packagecom.programcreek.test;importjava.io.IOException;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Properties;importcom.programcreek.db.DB;publicclassMain {
  • 極致查詢性能 sqltoy-orm-4.12.8 發版增加對國產達夢資料庫支持
    特點說明: 支持mysql、postgresql、db2、oracle、sqlserver、sqlite、clickhouse、elasticsearch、mongodb等 具有JPA模式的CRUD功能(即CRUD無需寫sql),無需寫Dao,sqltoy提供了SqlToyLazyDao,同時提供了
  • 開發崗位這麼多,為什麼選Java?你學Java了嗎-開課吧
    零基礎學Java主流開發語言根據最新2020年TIOBE程式語言指數排行榜,Java仍然排名前三位。零基礎學Java作為一門面向對象的高級語言,Java不僅吸收了C++語言的各種優點,還對C++裡諸如多繼承、指針等一些讓用戶難以理解和掌握的概念重新組織和及摒棄,從而形成了Java
  • BeetlSQL 3.1.2 發布,Java 資料庫訪問工具
    文件到Maven工程的路徑錯誤 代碼生成Pojo信息未包含主鍵信息 代碼生成math包導入錯誤 PageRequest 實現序列化接口<dependency> <groupId>com.ibeetl</groupId> <artifactId>beetlsql
  • sagacity-sqltoy 4.17.8 發布,Java ORM 框架
    sagacity-sqltoy 4.17.8 已經發布,此版本更新內容包括:1、支持緩存翻譯未匹配模板設置為空白或空字符串: uncached-template=""(之前空白當成無效設置
  • Java編程領域你需要懂得技術名詞解釋與常用開源框架理解
    IoC(DI)依賴注入實現的技術:反射機制、工廠模式。Dubbo(服務註冊管理),採用的是分布式調用,致力於提供高性能和透明化的RPC遠程服務調用方案,以及SOA服務治理方案。其側重服務的治理,將各個服務顆粒化,各個子業務系統在程序邏輯上完成業務的編排。
  • 滲透基礎之SQL注入
    註:其實xss[跨站腳本攻擊]也是對HTML的一種注入哦什麼是注入,這要先了解到SQL注入的發家史,SQL注入第一次出現是在1998年的黑客雜誌《Phrack》第54期,一名叫做rfp的黑客發表的一篇文章中,之後注入攻擊被大眾所知。
  • BeetlSQL 3.0.0-M1 第一個版本發布 - OSCHINA - 中文開源技術交流...
    相比於BeetlSQL2,新版支持更多數據來源,包括支持JDBC的傳統資料庫,大數據NOSQL,以及大數據SQL查詢引擎,在易用性何擴展性也做了大幅度修改。BeetlSQL3 能最大程度提高開發資料庫訪問的效率和增強相關代碼維護性BeetlSQL解決了很多資料庫訪問工具的不足 開發效率低,如mybatis,還需要搭配plus工具才能提高開發效率,而JOOQ這樣的又不適合複雜訪問 無SQL管理,遇到複雜的sql特別難維護,比如在Java裡拼寫sql,遇到調整就麻煩 跨資料庫平臺,即使
  • 老公,JNDI注入是什麼呀?
    而jndi注入就是利用的動態類加載完成攻擊的。在談jndi注入之前,我們先來看看關於jndi的基礎知識0x02 jndi是個啥jndi的全稱為Java Naming and Directory Interface(java命名和目錄接口)SUN公司提供的一種標準的Java命名系統接口,JNDI提供統一的客戶端API,通過不同的服務供應接口(SPI)的實現,由管理者將JNDI API映射為特定的命名服務和目錄系統,使得Java應用程式可以和這些命名服務和目錄服務之間進行交互
  • 如何學習Java,哪裡開始學Java比較好?
    找一套系統最新的基礎視頻:2020年最新Java基礎教程免費看  學習路線圖:2020年最新Java學習路線  社群或者社區(比如:csdn,B站等)學習  寫博客,把所學的知識點轉化成自己的,加強鞏固  做筆記,做思維導圖,做練習題  每個階段要做練手項目  給自己做一個學習規劃
  • Mybatis的sql組裝詳解
    上一篇分析了SqlSession執行sql的過程,其中並沒有分析sql是從哪裡來的,今天就來仔細分析下。Sql來源從上一篇的最後一步執行sql那裡倒推sql的來源,源碼主要過程如下圖:可以看到最後是通過BoundSql直接獲取的sql,然後往前倒推最後發現是通過MappedStatement的getBoundSql方法返回的。
  • 搞Java的你還不會Spring?一篇文章帶你掌握
    屬性注入屬性注入即通過setter方法注入Bean的屬性值或依賴的對象。屬性注入細節剛才大致地介紹了屬性注入和構造方法注入的步驟和一些注意事項,下面來了解一下屬性注入的細節。value="Audi" type="java.lang.String"></constructor-arg><constructor-arg value="ShangHai" type="java.lang.String"/><constructor-arg type="int"&
  • spring的java配置方式
    而且xml的配置方式,一旦配置多了,看起來雲裡霧裡,特別是對於只知道java代碼的小白來說,更重要的是xml文件不能做類型檢查,有時候你實際上是把一個錯誤的類裝配進接口,導致系統報錯,你卻要找半天錯誤。
  • java大數據和python大數據的全面對比,哪個更主流?
    大數據是目前網際網路流行的技術語言,處理大數據的程式語言比較有優勢的也很多,比如java、python、go、R語言、Hadoop等等,按道理來說每種程式語言都可以處理大數據,只是處理的規模不一樣而且,但是現在比較受歡迎的數據處理程式語言是java與python。
  • 跟我猜Spring-boot:依賴注入
    我們之前已經在工程中定義了SimpleService和SimpleController這兩個類,那麼這篇文章,我們要把SimpleService自動注入到SimpleController中;SimpleController.java