1. 程式人生 > 其它 >某租車系統JAVA程式碼審計

某租車系統JAVA程式碼審計

前言

由於開源的JAVA WEB專案不是很多,這裡找到一個沒有用struct2或是spring框架的cms,希望藉此cms來幫助新手敲開JAVA程式碼審計的大門,文章會詳細寫一些筆者進行審計過程走過的路,漏洞利用過程並不是多高深,大牛可以繞過,此篇權當拋磚引玉~

0x00 cms簡介

系統基於租車業務場景而搭建的O2O服務平臺,可為使用者提供商務租車、接送機、旅遊租車、企業租車、自駕租車、婚慶用車等自助租車服務。

系統包含車輛庫管理、門店管理、員工管理、司機管理、訂單管理、活動管理、評價管理、財務管理、統計等。

cms的下載地址:http://down.admin5.com/jsp/135501.html

下載完講一下安裝這塊,筆者的環境使用是tomcat8.5+phpmystudy,tomcat8.5部署web這個就不多說了,多百度百度自然就會了,這裡的phpmystudy主要是需要使用到其中的mysql資料庫,單獨開啟mysql資料庫也行~

這裡下載完有一個使用說明,對整個安裝流程介紹的還是非常詳細的,這裡不再贅述~

0x01 cms功能整理

這是網站首頁,然後我們來進行一個功能上的瀏覽與彙總,這裡可能是習慣問題,筆者在做程式碼審計的時候一般不會先看程式碼,而是根據功能點去進行一個程式碼的回溯,這樣做會減少大量的程式碼審計時間,但是缺點就是一些不在顯示頁面的功能點所存在的漏洞可能就會挖掘不到,這裡選擇可以因情況而異~

第一個功能點可能就是這個使用者的註冊功能,那使用者的註冊一般所存在的問題大多為sql注入、xss漏洞、邏輯漏洞、頭像處getshell等等,順著這樣的思路去找,效率上應該會大大提高。

第二個功能點可能就是這個主功能:租車服務。

但是這裡點選“立即預定”會跳轉到使用者介面,先放著,再看看其他功能點。

但是這個cms終究是一個小型的cms,整個功能不是很多,其餘功能點並未找到~

那麼我們來進行彙總!

審計的時候首先測試使用者功能點,這裡首先是最常見的一些邏輯漏洞(任意密碼重置這類)、SQL注入、儲存型xss漏洞、後臺頭像getshell、訂單遍歷等等,之後再測試租車功能,看看有無邏輯漏洞(1元購)和訂單遍歷(修改ID獲取其他使用者的資訊)等等,整個流程肯定大抵就是這樣,下面進入審計實戰!

0x02 cms審計實操

首先有一個獲取手機動態碼,那麼這裡由於是本地搭建,肯定發不出去,分析一下,這裡存在的潛在風險可能就是簡訊炸彈,這裡看了程式碼好像並沒有加上一些檢查機制,炸彈應該是存在的。

這裡說下怎麼進行程式碼的回溯,我是採用的search,比如說這裡的功能點為getTelCode,然後到eclipse中去進行全域性的搜尋,基本不到一分鐘就能定位到程式碼。

由於註冊功能不完善,這裡只能到後臺手工添加了一個賬號。

這裡的“忘記登入密碼”功能被閹割了,依然無法進行測試!

進入到個人中心,首先是功能點所引發的潛在漏洞彙總,映入眼簾的就是一個基本資料的修改:儲存型xss OR SQL注入??

包括這裡的資料修改和收貨地址修改其實都存在上述兩個問題,,這裡選擇一個進行程式碼跟蹤和測試即可~

訂單功能,會不會出現訂單的遍歷,那麼跟蹤程式碼就應該看對訂單的ID有無校驗?

優惠券這裡沒開放,最後就是積分功能,那麼會不會存在使用積分付費,然後由於校驗不完整,使用負積分付費從而導致積分反增不減這樣的漏洞出現?

首先測試來修改使用者的“基本資料”,這裡可以fuzz一下後臺語句,可以修改為woaini”<>,然後看回顯,,其實就可以大致猜出後臺程式碼。

修改完可以看到沒有任何的顧慮,那麼這裡的儲存型xss石錘!

雖然這裡是表單,但是後臺管理員檢視使用者資訊時卻不需要閉合表單,因此直接插入xss語句即可~

這裡再來找一下原始碼,看看到底怎麼寫的!

可以看到這裡都是直接request獲得,並沒有任何過濾,看程式碼的更大陰謀就是看看這裡的sql語句怎麼實現的,首先我們是登入使用者,然後姓名、地址、電話什麼的都沒輸錯,因此進入最後一個else語句。

flag=ss.addAddress(user.getId(), name, tel, address);   //這裡是用來實現sql語句的,跟進!-----------------------------------*分割線*----------------------------------------------------------    public Integer addAddress(Integer userId, String name, String tel, String address) {        Object args[] = { name, tel, address, userId };        String sql = "insert into user_address (user_address_name,user_address_tel,user_address_content,user_address_user) values(?,?,?,?)";        Serializable flag = jdbc.insertBackId(sql, args);                /*採用預編譯*/        jdbc.close();        return Integer.valueOf(flag.hashCode());    }

可以看到這裡的sql語句採用的是預編譯,因此sql注入漏洞可能不存在,但是預編譯最怕的就是字串的直接拼接,這裡在sql語句裡看了全部的sql語句,並不存在這樣的案例,因此sql這條路可能走到底了。

不過不用慌,繼續審計!下面來重點關注這個訂單功能,這是整個cms的核心所在!

這裡由於不存在數量這樣的引數,因此修改數量為負數這樣的情況並不存在,實際上是從session來獲取使用者的積分,因此積分上應該也不存在漏洞,最後只能提交訂單然後抓包看引數進行程式碼溯源~

這裡由於都是通過id這樣的引數來進行傳遞,那麼可以在審計的過程中留意id是否判斷所屬使用者,也就是越權的問題,最重要的可能就是這裡的price引數有無檢查!

然後全域性搜尋,找到可疑函式,確定為新增訂單的函式。

public void addGoodsOrder(HttpServletRequest request, HttpServletResponse response)throws ServletException,IOException{
        response.setContentType("text/html;charset=UTF-8");
        HttpSession session = request.getSession(true);
        Object ordinary_user=session.getAttribute("ordinary_user");
        String tem_store_id=request.getParameter("store_id");//門店id
        String price=request.getParameter("price");
        String tem_address_id=request.getParameter("address_id");
        String tem_goods_id[]=request.getParameterValues("goods_id");
        String content=request.getParameter("content");
        String serviceDate=request.getParameter("serviceDate");
        Integer store_id=null;
        Integer address_id=null;
        Integer goods_id=null;
        Integer order_id=0;
                    ……………略去部分程式碼……………
        if(ordinary_user==null){
            json="{"tip":"請登入之後再操作","status":500}";
        }else{
            User user=(User)ordinary_user; //這裡新增訂單資訊
            //order_id=ss.addGoodsOrder(2, 1, 1, 1,serviceDate, null, content, user.getId(),null, store_id, null, price, 1, 1, address_id, 2,"3", user.getId().toString(), null, goods_id, 1,"");
            if(order_id>0){
                if(tem_goods_id.length>0){
                    for(int i=0;i<tem_goods_id.length;i++){
                        ss.addGoodsAndOrder(Integer.parseInt(tem_goods_id[i]),order_id);
                    }
                }
                json="{"tip":"操作成功","status":200}";
            }else{
                json="{"tip":"伺服器內部錯誤","status":500}";
            }
}

這裡我們需要跟進這個ordinary_user,到這裡price這個引數都沒有任何過濾,是通過直接request請求獲取的。

這裡就不擷取程式碼了,可以明顯看到這裡的price引數依然沒有進行任何校驗,因此到這裡我們可以最終判斷,這個price引數可以進行任意修改!

這裡修改引數有兩種方法,第一種就是直接抓包修改即可,因為無任何校驗機制,所以可行。

第二種則是修改頁面的表單引數,這裡後來檢視付款原始碼,發現會在頁面中hidden傳過來的引數。

這裡通過修改頁面原始碼裡的value值也行~

進入到個人中心,這裡的訂單資訊獲取是通過session來獲取使用者,因此也就無法獲取他人的訂單資訊。

不過這裡有幾個功能,第一個就是取消訂單的功能,那麼對訂單編號是否進行了使用者歸屬的檢驗呢?讓程式碼來告訴我們!

這裡會將輸入的訂單與使用者自身的訂單號來進行一個匹配,若匹配成功才會取消訂單資訊,因此這裡不存在越權的漏洞!

那麼前臺的程式碼審計就告一段落,後臺的程式碼就先不看了~

這篇文章重點是講解一下筆者的JAVA程式碼審計的思路與方法,希望拋磚引玉,能夠有越來越多高質量的JAVA程式碼審計文章的出現~

上述如有不當之處,敬請指正!