Java利用技巧-通過反射修改屬性
0x00 前言
在上篇文章《Zimbra漏洞調試環境搭建》提到了通過反射枚舉JspServletWrapper實例的實現,本文將要以此為例,詳細介紹實現的思路和細節,便于以此類推,實現其他功能。
0x01 簡介
本文將要介紹以下內容:
?反射中的常用操作
?獲得類的所有字段
?獲得類的所有方法
?調用類的方法
?枚舉JspServletWrapper實例的實現細節
0x02 反射中的常用操作
1.獲得類的所有字段
getField():
能夠獲取本類以及父類中的public字段
getDeclaredField():
能夠獲取本類中的所有字段
這里以Zimbra環境為例,給出示例代碼
(1)獲取request對象的所有字段
(2)獲取request對象的父類的所有字段
2.獲得類的所有方法
getMethods():
能夠獲取本類以及父類或者父接口中的公共方法(public修飾符修飾的)
getDeclaredMethods():
能夠獲取本類中的所有方法,包括private、protected、默認以及public的方法
這里以Zimbra環境為例,給出示例代碼
(1)獲取request對象的所有方法
(2)獲取request對象的父類的所有方法
3.調用類的指定方法
這里以Zimbra環境為例,給出示例代碼
搭建好Zimbra漏洞調試環境后,定位request對象的getHeader(String name)方法,代碼細節如下:
對照代碼細節,參數類型為String
調用request對象的getHeader(String name)方法,參數為"User-Agent",實現代碼如下:
0x03 枚舉JspServletWrapper實例的實現細節
1.下斷點
選擇文件servlet-api-3.1.jar,依次選中javax.servlet->http->HttpServlet.class,在合適的位置下斷點,當運行到斷點時,可以查看request對象的完整結構,如下圖
查看request對象的結構,我們最終定位到了JspServletWrapper實例的位置,直觀的映射為:request->_scope->_servlet->rctxt->jsps
接下來,我們需要按照這個映射,通過多次反射最終獲得JspServletWrapper實例
(1)讀取request對象的所有字段
在回顯的結果中能夠找到_scope
(2)從request對象獲得_scope實例并再次枚舉字段
在回顯的結果中能夠找到_servlet
(3)獲得_servlet實例并再次枚舉字段
回顯的結果為:serialVersionUID
這里沒有rctxt字段
嘗試尋找原因:開啟調試器,定位至關鍵位置,如下圖
從圖中可以看到,_servlet的類為JettyJspServlet
JettyJspServlet繼承自JspServlet,成員變量只有serialVersionUID,這與我們通過訪問jsp頁面得到的結果一致
查看JspServlet的相關實現代碼,如下圖
從圖中可以看到,rctxt為JspServlet的成員變量,屬性為private,所以子類JettyJspServlet無法繼承成員變量rctxt
這里我們可以直接選取_servlet實例的父類進行枚舉字段
(4)選取_servlet實例的父類進行枚舉字段
在回顯的結果中能夠找到jsps
(5)獲得jsps實例并枚舉字段
開啟調試器,查看jsps的類型,如下圖
從圖中可以看到,jsps的類為ConcurrentHashMap,這里只需要枚舉出所有Key即可
添加需要導入的包后,得出最終實現代碼:
補充:刪除指定JspServletWrapper的實例
只需要調用ConcurrentHashMap的remove方法即可
示例代碼:
0x04 小結
本文介紹了通過反射枚舉JspServletWrapper實例的具體實現,記錄思路和細節,便于以此類推,修改其他內容。