攻擊JavaWeb應用[6]-程式架構與程式碼審計

wyzsk發表於2020-08-19
作者: 園長 · 2013/08/12 16:53

注:

不管多麼強大的系統總會有那麼些安全問題,影響小的可能僅僅只會影響使用者體驗,危害性大點的可能會讓攻擊者獲取到伺服器許可權。這一節重點是怎樣去找到並利用問題去獲取一些有意思的東西。

Before:

有MM的地方就有江湖,有程式的地方就有漏洞。現在已經不是SQL隱碼攻擊漫天的年代了,Java的一些優秀的開源框架讓其專案堅固了不少。在一箇中大型的Web應用漏洞的似乎永遠都存在,只是在於影響的大小、發現的難易等問題。有很多比較隱晦的漏洞需要在瞭解業務邏輯甚至是檢視原始碼才能揪出來。JavaWeb跟PHP和ASP很大的不同在於其安全性相對來說更高。但是具體體現在什麼地方?JavaWeb開發會有那些問題?這些正是我們今天討論的話題。

JavaWeb開發概念


Java分層思想

透過前面幾章的介紹相信已經有不少的朋友對Jsp、Servlet有一定了解了。上一節講MVC的有說的JSP+Servlet構成了效能好但開發效率並不高的Model2。在JavaWeb開發當中一般會分出很多的層去做不同的業務。

常見的分層

1、展現層(View 檢視) 
2、控制層(Controller 控制層) 
3、服務層(Service) 
4、實體層(entity 實體物件、VO(value object) 值物件 、模型層(bean)。
5、業務邏輯層BO(business object) 
6、持久層(dao- Data Access Object 資料訪問層、PO(persistant object) 持久物件)

依賴關係

在瞭解一個專案之前至少要知道它的主要業務是什麼主要的業務邏輯和容易出現問題的環節。其次是瞭解專案的結構和專案當中的類依賴。再次才是去根據業務模組去讀對應的程式碼。從功能去關聯業務程式碼入手往往比逮著段程式碼就看效率高無數倍。

前幾天在Iteye看到一款不錯的生成專案依賴圖的工具- Structure101,試用了下Structure101感覺挺不錯的,不過是收費的而且價格昂貴。用Structure101生成Jeebbs的專案架構圖:

enter image description here

Structure101匯入jeebss架構圖-包呼叫: 

enter image description here

Structure101包呼叫詳情:

enter image description here

Structure101可以比較方便的去生成類關係圖、呼叫圖等。Jeebbs專案比較大,邏輯相對複雜,不過可以看下我的半成品的部落格系統。

專案圖:

enter image description here

架構圖:

enter image description here

控制層:

enter image description here

呼叫流程(demo還沒處理異常,最好能try catch下用上面的logger記錄一下): 

enter image description here

漏洞發掘基礎


Eclipse採用的是SWT編寫,俗稱萬能IDE擁有各種語言的外掛可以寫。Myeclipse是Eclipse的外掛版,功能比eclipse更簡單更強大。

匯入Web專案到Myeclipse,Myeclipse預設提供了主流的Server可以非常方便的去部署你的Web專案到對應的Server上,JavaWeb容器異常之多,而ASP、 PHP的容器卻相對較少。容器可能除了開發者有更多的選擇外往往意味著需要除錯程式在不同的Server半桶的版本的表現,這是讓人一件非常崩潰的事。

除錯開源的專案需下載原始碼到本地然後匯入部署,如果沒有原始碼怎麼辦?一般情況下JavaWeb程式不會去混淆程式碼,所以透過之前的反編譯工具就能夠比較輕鬆的拿到原始碼。但是反編譯過來的原始碼並不能夠直接作用於debug。不過對我們瞭解程式邏輯和結構有了非常大的幫助,根據邏輯程式碼目測基本上也能完成debug。 

enter image description here

在上一節已經講過了一個客戶端的請求到達伺服器端後,後端會去找到這個URL所在的類,然後呼叫業務相關程式碼完成請求的處理,最後返回處理完成後的內容。跟蹤請求的方式一般是先找到對應的控制層,然後深入到具體的邏輯程式碼當中。另一種方法是事先到dao或業務邏輯層去找漏洞,然後逆向去找對應的控制層。最直接的如model1、model2並不用那麼費勁直接程式碼在jsp、servlet程式碼裡面就能找到一大堆業務邏輯。

按業務型別有序測試

普通的測試一般都是按功能和模組去寫測試的用例,即按照業務一塊一塊去測試對應的功能。這一種方式是順著了Http請求跟蹤到業務邏輯程式碼,相對來說比較簡單方便,而且邏輯會更加的清晰。

上面的架構圖和包截圖不知道有沒有同學仔細看,Java裡面的包的概念相對來說比較嚴禁。公認的命名方式是com/org.公司名.專案名.業務名全小寫。

如:org.javaweb.ylog.dao部署到伺服器上對應的資料夾應當是/WEB-INF/classes/org/javaweb/ylog/dao/其中的.意味著一級目錄。

現在知道了包和分層規範要找到控制層簡直就是輕而易舉了,一般來說找到Controller或者Action所在的包的路徑就行了。左邊是jeebbs右邊是我的blog,其中的action下和controller下的都是控制層的方法。@RequestMapping("/top.do")表示了直接把請求對映到該方法上,Struts2略有不同,需要在xml配置一個action對應的處理類方法和返回的頁面。不過這暫時不是我們討論的話題,我們需要知道隱藏在框架背後的請求入口的類和方法在哪。 

enter image description here

用例圖:

enter image description here

使用者註冊問題

使用者邏輯圖:

enter image description here

容易出現的問題:

1、沒有校驗使用者唯一性。
2、校驗唯一性和儲存資訊時拼Sql導致Sql注入。
3、使用者資訊(使用者名稱、郵箱等)未校驗格式有效性,可能導致儲存性xss。
4、頭像上傳漏洞。
5、使用者型別註冊時可控導致註冊越權(直接註冊管理員帳號)。
6、註冊完成後的跳轉地址導致xss。

Jeebbs郵箱邏輯驗證漏洞:

註冊的URL地址是:http://localhost/jeebbs/register.jspx, register.jspx很明顯是控制層對映的URL,第一要務是找到它。然後看他的邏輯。

Tips:Eclipse全域性搜尋關鍵字方法 

enter image description here

根據搜尋結果找到對應檔案:

enter image description here

根據結果找到對應的public class RegisterAct類,並檢視對應邏輯程式碼: 

enter image description here

找到控制層的入口後即可在對應的方法內設上斷點,然後傳送請求到控制層的URL進入Debug模式。 註冊傳送資料包時用Tamper data攔截並修改請求當中的email為xss攻擊程式碼。 

enter image description here

enter image description here

選擇任意物件右鍵Watch即可檢視對應的值(任意完整的,有效的物件包括方法執行)。 F6單步執行。

enter image description here

F5進入validateSubmit:

enter image description here

F6跟到125行註冊呼叫:

enter image description here

F3可以先點開registerMember類看看:

enter image description here

找到介面實現類即最終的註冊邏輯程式碼:

enter image description here

Jeebbs危險的使用者名稱註冊漏洞

Jeebbs的資料庫結構當中使用者名稱長度過長:

`username` varchar(100) NOT NULL COMMENT '使用者名稱'

這會讓你想到了什麼?

enter image description here

當使用者名稱的輸入框失去焦點後會傳送Ajax請求校驗使用者名稱唯一性。請輸入一個長度介於 3 和 20 之間的字串。也就是說滿足這個條件並且使用者名稱不重複就行了吧?前端是有使用者名稱長度判斷的,那麼後端程式碼呢?因為我已經知道了使用者名稱長度可以存100個字元,所以如果沒有判斷格式的話直接可以註冊100個字元的使用者名稱。首先輸入一個合法的使用者名稱完成客戶端的唯一性校驗請求,然後在點選註冊傳送資料包的時候攔截請求修改成需要註冊的xss使用者名稱,邏輯就不跟了跟上面的郵箱差不多,想像一下使用者名稱可以xss是多麼的恐怖。任何地方只要出現粗線下xss使用者名稱就可以輕易拿到別人的cookie。 

enter image description here

Cookie明文儲存安全問題: 

enter image description here

enter image description here

程式碼沒有任何加密就直接setCookie了,如果說cookie明文儲存使用者帳號密碼不算漏洞的話等會彈出使用者明文密碼不知道是算不算漏洞。

個性簽名修改為xss,發帖後顯示個性簽名處可xss 

enter image description here

因為個性簽名會在帖子裡顯示,所以回帖或者發帖就會觸發JS指令碼了。這裡說一下預設不記住密碼的情況下(不設定cookie)不能夠拿到cookie當中的明文密碼,這個漏洞用來打管理員PP挺不錯的。不應該啊,起碼應該過濾下。

不科學的積分漏洞

enter image description here

積分兌換方法如下:

@RequestMapping(value = "/member/creditExchange.jspx")
public void creditExchange(Integer creditIn, Integer creditOut, Integer creditOutType, Integer miniBalance, String password, HttpServletRequest request, HttpServletResponse response) {}

可以看到這裡直接用了SpringMvc注入引數,而這些引數恰恰是控制程式邏輯的關鍵。比如構建如下URL,透過GET或者POST方式都能惡意修改使用者的積分:

http://localhost/jeebbs/member/creditExchange.jspx?creditIn=26&creditOut=-27600&creditOutType=1&miniBalance=-10000000&password=wooyun

因為他的邏輯是這麼寫的:

if(user.getPoint()-creditOut>miniBalance){
    balance=true;
}else{
    flag=1;
}

從User物件裡面取出積分的數值,而積分兌換威望具體需要多少是在確定兌換關係後由ajax去後臺計算出來的,提交的時候也沒有驗證計算的結果有沒有被客戶端改過。其中的creditOut和miniBalance都是我們可控的。所以這個等式不管在什麼情況下我們都可以讓它成立。

enter image description here

打招呼XSS 邏輯有做判斷:

1、使用者名稱為空。
2、不允許傳送訊息給自己。
3、使用者名稱不存在。

在控制層並沒有做過濾: 

enter image description here

在呼叫com.jeecms.bbs.manager.impl. BbsMessageMngImpl.java的sendMsg方法的時候依舊沒有過濾。到最終的BbsMessageDaoImpl 的save方法還是沒有過濾就直接儲存了; 一般性的做法,關係到使用者互動的地方最好做referer和xss過濾檢測,控制層負責收集資料的同時最好處理下使用者的請求,就算controller不處理起碼在service層做下處理吧。

enter image description here

釋出投票貼xss釋出一片投票帖子,標題xss內容。

郵箱的兩處沒有驗證xss

個人資料全部xss

投稿打管理員後臺點選檢視觸發

搜尋xss

http://demo.jeecms.com/search.jspx?q=%2F%3E%3Cscript%3Ealert%28document.cookie%29%3B%3C%2Fscript%3Ehello&channelId=

漏洞N………

按程式實現逆向測試

”逆向”找SQL隱碼攻擊

SQL隱碼攻擊理論上是最容易找的,因為SQL語句的特殊性只要Ctrl+H 搜尋select、from 等關鍵字就能夠快速找到專案下所有的SQL語句,然後根據搜尋結果基本上都能夠確定是否存在SQL隱碼攻擊。凡是SQL語句中出現了拼SQL(如select * from admin where id=’”+id+”’)那麼基本上80%可以確定是SQL隱碼攻擊。但也有特例,比如拼湊的SQL引數並不受我們控制,無法在前臺透過提交SQL隱碼攻擊語句的方式去控制最終的查詢SQL。而採用預編譯?佔位方式的一般不存在注入。

比如搜尋51javacms專案當中的SQL語句: 

enter image description here

Tips:ORM框架特殊性

Hibernate HQL:

需要注意的是Hibernate的HQL是對物件進行操作,所以它的SQL可能是:

String hql = "from Emp";
Query q = session.createQuery(hql);

也可以

String hql = "select count(*) from Emp";
Query q = session.createQuery(hql);

甚至是

String hql = "select new Emp(e.empno,e.ename) from Emp e ";
Query q = session.createQuery(hql);

enter image description here

Mybatis(Ibatis3.0後版本叫Mybatis):

Ibatis、Mybatis的SQL語句可以基於註解的方式寫在類方法上面,更多的是以xml的方式寫到xml檔案。

enter image description here

在當前專案下搜尋SQL語句關鍵字,查詢疑似SQL隱碼攻擊的呼叫:

enter image description here

進入搜尋結果的具體邏輯程式碼:

enter image description here

最外層的Contrller: 

enter image description here

“逆向”找到控制層URL以後構建的SQL隱碼攻擊請求:

enter image description here

可能大家關注的程式碼審計最核心的怎麼去發掘SQL隱碼攻擊這樣高危的漏洞,其次是XSS等型別的漏洞。

小結:

學會怎樣Debug。
學會怎樣透過從控制層到最終的資料訪問層的程式碼跟蹤和從資料訪問層倒著找到控制層的入口。
學會怎樣去分析功能模組的用例。

檔案上傳、下載、編輯漏洞

檔案上傳漏洞即沒有對上傳的檔案的字尾進行過濾,導致任意檔案上傳。有的時候就算有字尾判斷,但是由於解析漏洞造成GETSHELL這是比較難避免的。

1、沒有做任何限制的上傳漏洞:

enter image description here

這一種是不需要任何繞過直接就可以上傳任意指令碼威脅性可想而知。

2、Bypass白名單和黑名單限制

enter image description here

某些時候就算做了字尾驗證我們一樣可以透過檢視驗證的邏輯程式碼找到繞過方式。第35、36行分別定義了白名單和黑名單字尾列表。41到46行是第一種透過黑名單方式校驗字尾合法性。47到57行程式碼是第二種透過白名單方式去校驗字尾合法性。現在來瞧下上訴程式碼都有那些方式可以Bypass。

1、假設37行程式碼的upload不是在程式碼裡面寫死了而是從客戶端傳入的引數,那麼可以自定義修改path把檔案傳到當前server下的任意路徑。
2、第39行犯下了個致命的錯誤,因為檔名裡面可以包含多個”.”而”xxxxx”.indexOf(“.”)取到的永遠是第一個”.”,假設我們的檔名是1.jpg.jsp即可繞過第一個黑名單校驗。
3、第42行又是另一個致命錯誤s.equals(fileSuffix)比較是不區分大小寫假設我們提交1.jSP即可突破驗證。
4、第50行同樣是一個致命的錯誤,直接用客戶端上傳的檔名作為最終檔名,可導致多個漏洞包括解析漏洞和上面的1.jpg.jsp上傳漏洞。

檔案上傳漏洞修復方案:

1、檔案上傳的目錄必須寫死
2、把原來的fileName.indexOf(".")改成fileName.lastIndexOf(".")
3、s.equals(fileSuffix)改成s.equalsIgnoreCase(fileSuffix) 即忽略大小寫或者把前面的fileSuffix字元轉換成小寫s.equals(fileSuffix.toLowerCase())

檔案下載漏洞

51JavaCms典型的檔案下載漏洞,我們不妨看下其邏輯為什麼會存在漏洞。51javacms並沒有用流行的SSH框架而是用了Servlert3.0自行做了各種封裝,實現了各種漏洞。Ctrl+H搜尋DownLoadFilePage找到下載的Servlet:

enter image description here

改裝了下51javacms的垃圾程式碼: 

enter image description here

請求不存在的檔案:

enter image description here

跨目錄請求一個存在的檔案:

enter image description here

enter image description here

檔案編輯漏洞

JeeCms之前的後臺就存在任意檔案編輯漏洞(JEECMS後臺任意檔案編輯漏洞and官方漏洞及拿shell :http://wooyun.org/bugs/wooyun-2010-04030)官方的最新的修復方式是把path加了StartWith驗證。

基於Junit高階測試


Junit寫單元測試這個難度略高需要對程式碼和業務邏輯有比較深入的瞭解,只是簡單的提下,有興趣的朋友可以自行了解。

JUnit是由 Erich Gamma 和 Kent Beck 編寫的一個迴歸測試框架(regression testing framework)。Junit測試是程式設計師測試,即所謂白盒測試,因為程式設計師知道被測試的軟體如何(How)完成功能和完成什麼樣(What)的功能。Junit是一套框架,繼承TestCase類,就可以用Junit進行自動測試了。

enter image description here

其他


1、透過檢視Jar包快速定位Struts2漏洞

比如直接開啟lerxCms的lib目錄:

enter image description here

2、報錯資訊快速確認Server框架

型別轉換錯誤:

enter image description here

Struts2:

enter image description here

3、二次校驗邏輯漏洞

比如修改密保郵箱業務只做了失去焦點唯一性校驗,但是在提交的時候聽沒有校驗唯一性

4、隱藏在Select框下的邪惡

Select下拉框能有什麼漏洞?一般人我不告訴他,最常見的有select框Sql注入、儲存性xss漏洞。搜尋注入的時候也許最容易出現注入的地方不是搜尋的內容,而是搜尋的條件!

Discuz select下拉框儲存也有型別的問題,但Discuz對Xss過濾較嚴未造成xss:

enter image description here

下拉框的Sql注入: 

enter image description here

enter image description here

小結: 本節不過是漏洞發掘審計的冰山一角,很多東西沒法一次性寫出來跟大家分享。本系列完成後公佈ylog部落格原始碼。本節原始碼暫不釋出,如果需要原始碼站內。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章