關於Mybatis的SQL注入


前言:最近在學Mybatis,趁機把Mybatis框架下可能引發的SQL注入來過一遍,加深理解

Mybatis傳遞數據有兩種方式,一種是#{},還有一種是${},而#{}基本能防止SQL注入,但是某些環境下需要用到${},所以可能就會導致SQL注入的產生

大概產生SQL注入的有如下幾種類型,自己都會詳細的記錄,以及自己的思考

1、模糊查詢like

2、in之后的參數

3、order by

數據表userinfo的數據如下:

模糊查詢like

Mapping.xml

    <!--like下的SQL注入-->
    <select id="getUserByName" parameterType="String" resultType="com.zpchcbd.pojo.User">
        select * from userinfo where name like "%"#{name}"%"
    </select>

業務代碼:

    public static void test06(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.getUserByName("六");
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

首先一開始想要實現先試試如下

select * from userinfo where name like '%#{name}%'

發現會報錯,它根本識別不了索引值來進行替換

那么如果將SQL語句改成如下為,發現能正常的查詢出數據!

select * from userinfo where name like '%${name}%'

發現用${}來執行的SQL語句,最終的SQL語句為如下,也就是只是單純的替換了,連預編譯的工作都沒有進行處理!

select * from userinfo where name like '%六%'

如果我們此時加一個單引號則會出現報錯!

到目前則證明了如果使用${},則是使用拼接SQL語句的方法,那么就會造成SQL注入,但是如果想要預防SQL注入試圖通過#{}來寫,又會發生報錯!

所以對於模糊查詢like的SQL注入就是這樣子產生的,一般人就會使用${}來進行查詢,修復方法就是自己還需要手動加一層過濾才行

自己又想了下那么如果SQL語句是這樣呢?select * from userinfo where name like "%"#{name}"%"

發現它是可以查詢的,並且會進行預編譯操作,最終的SQL語句為如下:select * from userinfo where name like "%"'六'"%";,這種自己沒見過,猜想是不是在mysql中可能就是單引號和雙引號會自動進行拼接?那這種可以作為一種繞過方法嗎?還需要去研究或者有懂的人可以告知下!

到這里,我們其實就可以明白了${} #{} 本質到底做了什么事,${}這個東西就是我們正常在寫SQL語句中的進行拼接的操作,這種是十分可能引起SQL注入的,然而#{}則是經過預編譯的操作,其實也就是一個占位符?,預編譯會自動給你兩邊加上單引號,並且對其中的非法字符進行轉義操作,最終預防了SQL注入的產生!

但是一旦跟業務掛鈎之后,SQL注入就十分容易的產生!

in之后的參數

繼續來in的SQL注入

Mapper.xml

    <select id="getUserById" resultType="com.zpchcbd.pojo.User">
        select * from userinfo where id in (${id})
    </select>
    // getuser by id
    public static void test02(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //方式一
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserById("1,2,3");
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();
    }

先是傳遞"1,2,3",發現在#{}的情況下也可以正常查詢,但是只能查詢到一條,原因同樣是預編譯的影響,最終的SQL語句為select * from userinfo where id in ('1,2,3')

當改成${}的時候,則最終查詢的記錄為3條,SQL語句為:select * from userinfo where id in (1,2,3)

所以才會導致SQL注入的產生,其實都是跟業務掛鈎

order by

參考之前寫過的:https://www.cnblogs.com/zpchcbd/p/14725943.html

官方文檔對${}和#{}的介紹:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html

參考文章:https://mp.weixin.qq.com/s?__biz=MjM5OTk2MTMxOQ==&mid=2727827368&idx=1&sn=765d0835f0069b5145523c31e8229850&mpshare=1&scene=1&srcid=0926a6QC3pGbQ3Pznszb4n2q


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM