1. 程式人生 > >Java審計之SQL注入篇

Java審計之SQL注入篇

# Java審計之SQL注入篇 ## 0x00 前言 本篇文章作為Java Web 審計的一個入門文,也是我的第一篇審計文,後面打算更新一個小系列,來記錄一下我的審計學習的成長。 ## 0x01 JDBC 注入分析 在Java裡面常見的資料庫連線方式也就那麼幾個,分別是JDBC,Mybatis,和Hibernate。 ### 注入常見場景分析 JDBC的連線是比較繁瑣的,並且是最原始的連線方式,我們來看看JDBC的最原始的連線程式碼 Get型注入: ``` @WebServlet("/demo") public class domain extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get訪問"); String id = req.getParameter("id"); Connection conn = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/demo", "root", "root"); String sql = "select * from users where id = '"+id+"' "; Statement statement = conn.createStatement(); ResultSet resultSet = statement.executeQuery(sql); } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } } ``` 這裡編寫了一個serlvet獲取get的值,連線資料庫使用了jdbc的方式進行連線,採用了拼接的方式直接拼接到了sql語句裡面去。這樣的程式碼如果在傳入前沒做過濾直接拼接,就會產生sql注入。 在實際運用當中如果不採用框架使用JDBC的方式,普遍會編寫一個工具類來完成這些繁瑣的配置,但是具體的實現還是呼叫這些方法來進行實現,只是進行了一個簡單的封裝。 在程式碼審計的時候,如果看到是JDBC的方式進行連線可以跟蹤一下他的程式碼,看他有沒有呼叫自己定義的過濾方法,如果沒有的話,就會存在sql注入,當然這是在未使用預編譯的情況下。 後面的重複的比較多,都是大致相同,我後面就貼出一些主要的程式碼進行分析。 POST型注入: ``` String sql = "select * from users where username = '"+username+"' and password = '"+password+"' "; ``` GET的注入和POST的其實差不多,只是獲取值的地方不一樣。 Like型注入: ``` String name = req.getParameter("name"); String sql = "select * from users where name like '%'+name+'%'"; ``` Header注入: ``` String referer = req.getHeader("referer"); String sql = "update user set referer ='"+referer+"'"; ``` 以上列了幾種方式都是JDBC採用拼接的方式造成SQL注入的程式碼。 ### JDBC 預編譯 預編譯的定義其實就是使用問號先來佔位,後面再傳入具體的值。 後面傳值的時候,程式會把傳入的引數,自動轉換為spring型別的字元,並不會拼接成sql語句生效。 ``` Connection conn = JDBCUtils.getConnection(); String sql = "select * from users where username = ? and password = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); //使用預編譯傳入sql語句 pstmt.setString(1,username); //設定第一個引數為username pstmt.setString(2,password); //設定第二個引數為password pstmt.executeQuery(); ``` ## 0x02 Mybatis 注入分析 Mybatis獲取值的方式有兩種,分別是`${}` 和 `#{}`。 ``` #{}:解析的是佔位符問號,可以防止SQL注入,使用了預編譯。 ${}:直接獲取值 ``` 在Mybatis裡面一般會採用`#{}`來進行取值,但是也會有特殊情況。 ### like注入: 我們這裡還是以程式碼做演示 ``` select id="findlike" resultType="com.test.domain.User" parameterType="string"> select * from user where name like '%#{name}%', ``` 我們在執行的時候會發現,程式碼直接就會丟擲異常。 正確程式碼: ``` select id="findlike" resultType="com.test.domain.User" parameterType="string"> select * from user where name like '%${name}%', ``` 需要使用${}的方式進行取值。 或者是 ``` ``` 測試類: ``` public void findlike(){ List ming = userDao.findlike("'%'+xiao+'%'"); for (User user1 : ming) { System.out.println(user1); } } ``` 另外還有種寫法: ``` ``` 這裡在前面進行加入兩個`%`,再進行傳入這樣的方式也不會報錯,但是使用 `#`直接拼接`%`就會報錯。 like不能直接使用預編譯,如果在沒處理好引數的情況下進行傳入,也是會產生sql注入的。 ### in後注入 ``` Select * from news where id in (#{id}), ``` 也是拼接使用預編譯這樣的程式碼也會報錯。 正確寫法: ``` Select * from news where id in (${id}) ``` ### order by 注入 ``` Select * from news where title ='#{titlename}' order by #{time} asc ``` 執行會報錯 正確寫法: ``` Select * from news where title ='#{titlename}' order by ${time} asc ``` ## 0x03 CMS 審計 ### 測試環境 ``` IDEA :2020.1.2 X64 MYSQL :5.7.26 TomCat:8.0 JDK :1.8 ``` ### 搭建環境 下載原始碼 `http://down.admin5.com/jsp/132874.html`。 idea中匯入專案,新增pom.xml檔案為maven檔案。如果Spring註解報錯說明Spring的環境還沒拉去下來,重新整理一下pom.xml檔案就好了。 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910183706529-1061160626.png) 這裡配置是82埠,目錄就預設就行。 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910183938252-781247501.png) 配置tomcat也設定為82埠 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910183814997-1047270174.png) 這裡要注意路徑需要根路徑,否則載入有一些css資源的時候路徑會因為路徑問題載入不少。 這樣就配置完成了,但是還是會發現有一些get,set的方法會爆紅。 專案的說明文件裡面給出瞭解決方法,只需要安裝一下lombok外掛重啟一下就解決了,這裡是因為一些程式碼中並沒有實際編寫get和set的方法,使用的是外掛去提供的。 這些完成後,就可以講提供好的sql檔案匯入進去。進行啟動 這些都是自己專門踩過的坑,一段操作猛如虎後,啟動完成。但是會有一些報錯,sql檔案在匯入的時候,有些執行錯誤了,幾張表沒建立成功,在進行操作該表的時候未找到該表,就報錯了。 將就一下把! ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184022560-2050140286.png) 第一步肯定是先看他的web.xml的配置,看他都使用了哪些框架 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184041507-1513285487.png) 確實該cms是一個使用了SSM框架,也就是Spring+Spring Mvc+Mybatis (哈哈哈,其實是看說明文件知道的。) ### 審計SQL 注入 檔案的劃分很細,很清楚看到他的結構,點開dao檔案下的任意檔案,看看Mybatis是使用了註解開發還是配置檔案開發。 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184053419-1946514213.png) 點開沒發現有Mybatis的註解,那就肯定是使用了配置XML的方式。 對映檔案會和dao的介面在同層目錄下。 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184105737-420870778.png) 直接就來找`$`符號吧,看看哪些是直接呼叫了`$`來進行取值並且沒經過過濾的。 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184225493-1816776807.png) 發現deleteArticleByIds使用的是`$`取值。 找到配置檔案對應的dao介面 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184235137-2078281337.png) 選中dao介面中deleteArticleByIds,Curl+左鍵可以看到哪些類呼叫了該方法。 我這裡就跳轉到了service層的一個實現類裡面。 主要關注service層程式碼,過濾處理的會從service層去實現。 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184248971-327849803.png) 並沒有發現過濾的程式碼 接下來就可以去找該service對應的Controller,這個可以使用idea的ctrl+Alt+H快捷鍵去查詢呼叫層次,去看Controller的位置。 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184319751-525702464.png) ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184336092-247833219.png) 檢視到了Controller檔案,先找他的目錄路徑 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184816980-99616241.png) ``` /admin/article ``` 在搜尋一下deleteArticleByIds具體在哪裡呼叫和出現,就得到了具體的漏洞位置。 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184851065-665660262.png) 漏洞位置: ``` http://127.0.0.1:82/admin/article/delete ``` 訪問漏洞位置 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184905403-1671983997.png) 點選刪除進行抓包 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184913475-1950597444.png) 扔到sqlmap跑一下 ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184933820-782946881.png) ![](https://img2020.cnblogs.com/blog/1993669/202009/1993669-20200910184941362-1040994071.png) ### 參考文章 ``` https://mp.weixin.qq.com/s?__biz=MjM5OTk2MTMxOQ==&mid=2727827368&idx=1&sn=765d0835f0069b5145523c31e8229850&mpshare=1&scene=1&srcid=0926a6QC3pGbQ3Pznszb4n2q https://xz.aliyun.com/t/2646#toc-1 ``` ## 0x04 結尾 前面的環境配置了比較久,耽誤了不少時間。