Skip to content

Commit

Permalink
Merge pull request payara#5198 from Pandrex247/FISH-1274-Comm
Browse files Browse the repository at this point in the history
FISH-1274 Vulnerability in Metro's WSDL Code Importing/Parsing - Remote Code Execution
  • Loading branch information
Pandrex247 authored and JamesHillyard committed Oct 8, 2021
1 parent 6bfec80 commit 37a1eff
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ public static void invoke(HttpServletRequest request, HttpServletResponse respon
WebServiceTesterServlet servlet = new WebServiceTesterServlet(endpoint);

response.setCharacterEncoding("UTF-8");

// Validate Host Header to help prevent Host Header Attacks
if (!servlet.isValidHostHeader(request)) {
throw new ServletException("Host Header does not appear to be valid - it does not appear to be a " +
"valid IPv6 literal, IPv4 dotted-decimal, or DNS name.");
}

if (request.getMethod().equalsIgnoreCase("GET")) {
servlet.doGet(request, response);
} else {
Expand Down Expand Up @@ -645,4 +652,64 @@ private void deleteDir(File path) {
private String encodeHTML(String html) {
return html.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
}

/**
* Method to test that the Host Header is valid and doesn't have any illegal characters, to help prevent Host Header
* Attacks.
*
* @param request The {@link HttpServletRequest} from the
* {@link WebServiceTesterServlet#invoke(HttpServletRequest, HttpServletResponse, WebServiceEndpoint)} method
* @return True if the Host Header is valid, false if it isn't
*/
private boolean isValidHostHeader(HttpServletRequest request) {
// Get the Host Header
String serverName = request.getServerName();

// Decode the Host Header
String decodedServerName = null;
try {
decodedServerName = URLDecoder.decode(serverName, "UTF-8");
} catch (UnsupportedEncodingException unsupportedEncodingException) {
logger.log(Level.WARNING, "Could not decode URL during validation, assuming Host Header is invalid.",
unsupportedEncodingException);
return false;
}

// Shouldn't Happen™, but just in case
if (decodedServerName == null) {
logger.log(Level.WARNING, "Host Header decoded to null during validation, assuming Host Header is invalid.");
return false;
}

// Check IPv6 literal: []
if (decodedServerName.startsWith("[") && decodedServerName.endsWith("]")) {
return true;
}

// Check IPv4 dotted-decimal: xxx.xxx.xxx.xxx
if (checkValidIpv4DottedDecimal(decodedServerName)) {
return true;
}

// Check DNS name is valid - ASCII alphanumerics and "-" only, no segment longer than 63 characters,
// sections separated with ".", possibly ending with "."
if (checkValidDnsName(decodedServerName)) {
return true;
}

// No match implies invalid host header / server name
return false;
}

// Split off for unit testing
protected static boolean checkValidIpv4DottedDecimal(String decodedServerName) {
return decodedServerName.matches(
"^((0|1\\d?\\d?|2[0-4]?\\d?|25[0-5]?|[3-9]\\d?)\\.){3}(0|1\\d?\\d?|2[0-4]?\\d?|25[0-5]?|[3-9]\\d?)$");
}

// Split off for unit testing
protected static boolean checkValidDnsName(String decodedServerName) {
// NOTE: HttpServletRequest.getServerName strips the port so no need to check
return decodedServerName.matches("((?!-)[\\w-]{1,63}(?<!-)(\\.|$))+");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2021 Payara Foundation and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://github.com/payara/Payara/blob/master/LICENSE.txt
* See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* The Payara Foundation designates this particular file as subject to the "Classpath"
* exception as provided by the Payara Foundation in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package org.glassfish.webservices.monitoring;

import org.junit.Assert;
import org.junit.Test;

public class WebServiceTesterServletTest {

@Test
public void testIpv4Regex() {
// Loopback should work
Assert.assertTrue(WebServiceTesterServlet.checkValidIpv4DottedDecimal("127.0.0.1"));

// Typical default should work
Assert.assertTrue(WebServiceTesterServlet.checkValidIpv4DottedDecimal("192.168.1.1"));

// Empty string should fail
Assert.assertFalse(WebServiceTesterServlet.checkValidIpv4DottedDecimal(""));

// DNS name should fail
Assert.assertFalse(WebServiceTesterServlet.checkValidIpv4DottedDecimal("payara.fish"));

// All 0's allowed
Assert.assertTrue(WebServiceTesterServlet.checkValidIpv4DottedDecimal("0.0.0.0"));

// No 0 prefixes
Assert.assertFalse(WebServiceTesterServlet.checkValidIpv4DottedDecimal("012.168.35.64"));

// 0 suffixes allowed
Assert.assertTrue(WebServiceTesterServlet.checkValidIpv4DottedDecimal("102.120.35.240"));

// Numbers greater than 255 not allowed
Assert.assertFalse(WebServiceTesterServlet.checkValidIpv4DottedDecimal("192.168.43.256"));
Assert.assertFalse(WebServiceTesterServlet.checkValidIpv4DottedDecimal("192.168.43.1234"));

// Must be 4 segments
Assert.assertFalse(WebServiceTesterServlet.checkValidIpv4DottedDecimal("192"));
Assert.assertFalse(WebServiceTesterServlet.checkValidIpv4DottedDecimal("192.168"));
Assert.assertFalse(WebServiceTesterServlet.checkValidIpv4DottedDecimal("192.168.43"));
}

@Test
public void testDnsNameRegex() {
// Standalone name allowed e.g. "localhost"
Assert.assertTrue(WebServiceTesterServlet.checkValidDnsName("payara"));

// "." allowed to denote segments
Assert.assertTrue(WebServiceTesterServlet.checkValidDnsName("payara.fish"));

// "-" is allowed
Assert.assertTrue(WebServiceTesterServlet.checkValidDnsName("payara-jaxws"));

// "-" is allowed, and "." allowed to denote segments
Assert.assertTrue(WebServiceTesterServlet.checkValidDnsName("payara-jaxws.fish"));

// Letters and numbers allowed
Assert.assertTrue(WebServiceTesterServlet.checkValidDnsName("payara2021"));

// Multiple segments allowed, and letters & numbers allowed
Assert.assertTrue(WebServiceTesterServlet.checkValidDnsName("payara.2021.swims"));

// "-" is allowed, "." allowed to denote segments, and so is a trailing "."
Assert.assertTrue(WebServiceTesterServlet.checkValidDnsName("payara-jaxws.fish."));

// Double trailing "." not allowed
Assert.assertFalse(WebServiceTesterServlet.checkValidDnsName("payara-jaxws.fish.."));
// No non-ASCII alphanumerics allowed
Assert.assertFalse(WebServiceTesterServlet.checkValidDnsName("faß.de"));
// No symbol other than "-" or "." allowed
Assert.assertFalse(WebServiceTesterServlet.checkValidDnsName("malicious/payload.wsdl"));
Assert.assertFalse(WebServiceTesterServlet.checkValidDnsName("malicious/payload.wsdl#"));
}

}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
<maven.compiler.plugin.version>3.8.0</maven.compiler.plugin.version>
<maven.compiler.showDeprecation>true</maven.compiler.showDeprecation>
<maven.jar.plugin.version>3.1.1</maven.jar.plugin.version>
<maven.surefire.plugin.version>3.0.0-M3</maven.surefire.plugin.version>
<maven.surefire.plugin.version>3.0.0-M5</maven.surefire.plugin.version>
<maven.resources.plugin.version>3.1.0</maven.resources.plugin.version>
<maven.release.plugin.version>2.5.3</maven.release.plugin.version>
<maven.dependency.plugin.version>3.1.1</maven.dependency.plugin.version>
Expand Down

0 comments on commit 37a1eff

Please sign in to comment.