SSD Advisory – Oracle Java FTP Stream Injection

Credit to Author: Maor Schwartz| Date: Tue, 21 Feb 2017 13:51:34 +0000

Vulnerability Summary
The following advisory describes a FTP protocol stream injection vulnerability found in Oracle Java. Java is a general-purpose computer programming language that is concurrent, class-based, object-oriented, and specifically designed to have as few implementation dependencies as possible. It is intended to let application developers “write once, run anywhere” (WORA).

Credit
An independent security researcher has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program

Vendor response
We have reported this vulnerability to Oracle, and have been waiting for several months for a patch for this vulnerability. Another researcher has discovered this vulnerability and went public with it – at which point we decided to publish the information without waiting for Oracle to release a patch.

Vulnerability Details
Java is vulnerable to an FTP protocol stream injection via malicious URLs. If an attacker can cause Java application to retrieve a malicious URL of this type, then the attacker can inject FTP commands into the client’s protocol stream.

For example, the following URL allows for new lines (CRLF) to be injected in the TCP stream, making the receiving server think that “NEW COMMAND” is a separate command sent by the client:

The above URL, when fetched by Java, causes the following partial command sequence to be sent:

Java is vulnerable to this injection via multiple fields in the URL. The username field and the directory path specified in the URL.

There are 2 main scenarios to exploit the vulnerability:

  1. XML External Entity (XXE) Exfiltration
  2. Opening Ports in the Firewall

Attack Scenario 1: XML External Entity (XXE) Exfiltration

If an application is vulnerable to XML External Entity (XXE), then this makes it easier to successfully use Out-Of-Band (OOB) exfiltration of file contents and similar data. An example for a hypothetical attack:

In this example, the file located at http://evil.com/evil.dtd would contain:

This would cause the contents of the win.ini file to be sent to the attacker’s FTP server as part of the PASS command. While similar attacks have been demonstrated with HTTP URLs previously, this is useful because Java’s HTTP URL validation has become more strict in recent years and will not allow many special characters in URLs that used to be allowed in previous versions. The FTP URL handler is far more lax, particularly in the password field.

Attack Scenario 2: Opening Ports in the Firewall

If an attacker can cause victim system to fetch an FTP URL with Java, and the victim’s firewall supports classic, non-passive FTP inspection and translation, then this attack can be conducted:

Opening Ports in the Firewall Attack Scenario Proof of Concept

First Challenge: Determining Internal IP
In this scenario, the attacker needs to know the victim’s internal IP address. The attacker can send a prob URL, see how the client behaves, then try another until the attack is successful (Only 2-3 attempts should be required).

As for the first phase of the attack, the attacker can simply supply the victim with an FTP URL that points to an unusual port on the attacker’s server, such as:

Assuming the attacker’s server rejects any passive commands, the Java client will fall back to using classic non-passive modes. When the client sends the PORT command, it is unlikely this will be translated by the victim’s firewall, since it is on an unusual port. That means the client will be handing the attacker it’s internal IP address.

Second Challenge: Packet Alignment

FTP is designed as a synchronous, line-based protocol where each side of the communication writes one line and waits for a response from the other side before continuing. That means neither side of the communication should write more than one command before waiting for the other to respond.

The Linux conntrack firewall modules take advantage of this fact to try and be extra sure that they really are seeing a PORT command on the wire. They implement this by requiring any PORT command to appear at the very beginning of the packet. Therefore, the URL (shown earlier) doesn’t actually cause Linux firewalls to open up the desired port:

If you carefully observe the packet trace of the above URL being fetched, you’d see commands sent by the client coming in the following individual packets:

Since the PORT command comes in the middle of Packet 4, Linux ignores it.

To force the client to send the PORT command at the very beginning of a packet, even though two commands were sent in a single write, we will use CWD command with directory name that is long enough that it exactly filled up one TCP packet, Then “PORT…” would be forced to start at the very next packet.

There are several difficulties to exploiting this vulnerability, MTU size may be high, Java application may complain about receiving a very long URL. To overcome this, we can simply force the FTP session’s TCP connection to use the minimum MTU size, since we control the malicious FTP server. Linux firewall rules can be use to clamp the MSS to 536 bytes, which makes our malicious URLs much easier to calculate.

Getting Java our URLs

There are a variety of situations where we could convince a Java application to fetch our URLs, which we discuss briefly here.

  1. SSRF: If an application accepts any HTTP, HTTPS, or FTP URL, then exploitation is straight-forward. Even if the application accepts only HTTPS or HTTP URLs due to naive input validation, then an attacker could simply redirect to a malicious FTP URL.
  2. XXE: Most XXE bugs yield SSRF like access, so this is pretty straight forward. Note that some XXE vulnerabilities aren’t very practical to exploit due to XML parser settings, preventing classic entity attacks. However, in some of these cases SSRF is still possible.
  3. Man-in-the-Middle: If a Java application is fetching any HTTP URL, then a privileged network attacker could inject a redirect to bootstrap this attack.
  4. JNLP Files: If a desktop user could be convinced to visit a malicious website while Java is installed, even if Java applets are disabled, they could still trigger Java to parse a JNLP file. These files could contain malicious FTP URLs which trigger this bug. A clever attacker could weaponize the exploit to determine the victim’s internal IP address, determine the appropriate packet alignment, and then exploit the bug all in one shot. Many ports could be opened at once, potentially. I have not tried this, but it should be possible with a clever implementation.

General Setup
Set up 3 systems, each running Debian Linux. One system is the external attacker server (EAS), another is the victim firewall (VF), and the third is the victim target (VT). They should be arranged in a very simple configuration like this:

EAS —– VF —– VT

For the purposes of this document, let’s assume these hosts have the following IP addresses:

  1. EAS: 1.3.3.7
  2. VF: 8.14.14.15
  3. VT: 10.1.2.3

Victim Firewall (VF) Setup
Victim Firewall (VF) will need to be configured with a NAT firewall:

Then we will load the nf_conntrack_ftp and nf_nat_ftp kernel modules and set a couple of FORWARD rules to allow the modules to work:

In these rules, the 10.0.0.0/24 network is considered internal. The first forward rule above just allows all traffic outbound. The second rule allows non-passive FTP connections to connect back to clients, so long as the conntrack modules have determined the FTP client wants that connection to come back.

Victim Target (VT) Setup
Make sure Java is installed and ‘java‘, ‘javac‘ and ‘javaws‘ binaries are in $PATH. Also be sure socat and netcat are installed

Copy the following code (we will call it fetch) to the Victim Target (VT) system and compile (javac ) it:

The Victim Target (VT) host should run service to observe when the Attacker Server (EAS) system connects to it:

Whatever TCP port is chosen for this should be one that the Victim Firewall (VF) doesn’t ordinarily forward to the Victim Target (VT). It should also be a “high” port (>=1024).

Attacker Server (EAS) Setup
The Attacker Server (EAS) system will need a bit of configuration as well. Copy the following script (we will name him ftp-injection-server.py) to The Attacker Server (EAS) and be sure you are logged in as root.

Next, the following firewall rule should be added to implement the MSS clamping (to be clear: we’re running this on the attacker’s server, not the victim firewall):

Step 0: Determine the Victim’s Internal IP

Run the ftp-injection-server.py script on a high port:

Next, run fetch on the Victim Target (VT) with a URL that points to this high port service:

This should cause the Attacker Server (EAS) FTP service to response something like:

Step 1: Verify Victim Firewall (VF) is Translating PORT/EPRT Commands

Let’s make sure your firewall is behaving as we expect – stop the FTP server script if is is already running and start it again:

The first IP address is the external IP of the Attacker Server (EAS), the second is the internal IP of the Victim Target (VT), and the last argument is the port number we would like to open up for attack.

Next, run a non-malicious FTP fetch to see if the firewall translates this port 21 traffic:

You should see the Attacker Server (EAS) service to response something like:

Step 2: Determine CWD Padding Length

The FTP server script will automatically determine the correct packet offset by first asking you to fetch a long URL via the vulnerable client, and then calculating what the correct padding length is.

Restart the FTP server script with the same arguments from Step 1.

It should response a message like this upon startup:

Copy and paste this URL into a command on the Victim Target (VT):

The directory with all of the padding (X’s) is too long for one packet, but upon fetching this, the FTP server will calculate the correct URL to use for success.

You should now see something like this on the EAS console:

This final URL should be usable going forward for any number of TCP connections you want to initiate to the Victim Target (VT).

Step 3: Open the Firewall and Test the Service

Keep the FTP service running with the same configuration from Step 2. Just do a final fetch to open up the port through the firewall:

This should cause the FTP service to response something like this:

If you see the “Correct padding!” message, then the FTP service thinks the attack worked. It will immediately spawn a socat process which relays a single TCP connection to the Victim Target (VT). This is done because the Victim Firewall (VF) might time-out the data connection for the FTP command if you don’t act quickly. By spawning a socat child process, we get the connection established and can hold on to it longer.

The “Setting up relay…” message indicates which local TCP port that socat is now listening on. To send a bit of data through this relay, run (using the port mentioned in this message):

Then observe the listening netcat process running on the Victim Target (VT). The word “pwned” should show up on STDOUT.

Step 4: Try Java Network Launch Protocol (JNLP) Attacks

Once you have an FTP URL that works for you in Step 3, you could try the attack from Java WebStart. Edit the the following code (we will call it evil.jnlp) and replace the “codebase” attribute in the top level “jnlp” tag, placing your working URL in it. Then just run this on the Victim Target (VT) – javaws evil.jnlp

This will cause Java to try and fetch application components from FTP URLs that trigger the injection. JNLP files are easy to put in web pages, so this is how an attacker trigger the flaw in phishing or drive-by scenarios. Since JNLP files will be parsed by Java even if the browser plugin is disabled, it is a reasonably probable attack scenario.

https://blogs.securiteam.com/index.php/feed