211 lines
12 KiB
Diff
211 lines
12 KiB
Diff
diff --git a/ChangeLog b/ChangeLog
|
|
index 0c63dd98..d8e560e0 100644
|
|
--- a/ChangeLog
|
|
+++ b/ChangeLog
|
|
@@ -1,3 +1,29 @@
|
|
+2019-06-26 Jiri Vanek <jvanek@redhat.com>
|
|
+
|
|
+ All files, except signaturre files, are now checked for signatures - CVE-2019-10181
|
|
+ * b/netx/net/sourceforge/jnlp/tools/JarCertVerifier.java: (isMetaInfFile) fixed bug, when anything in META-INF was not
|
|
+ checked for signature. Now only signature files are skipped
|
|
+ * tests/netx/unit/net/sourceforge/jnlp/tools/JarCertVerifierTest.java: added tests for check if file should be skipped from
|
|
+ signature check
|
|
+
|
|
+2019-06-26 Jiri Vanek <jvanek@redhat.com>
|
|
+
|
|
+ Nested jar, if by relative path point up, is stored as hashed - CVE-2019-10185
|
|
+ * tests/netx/unit/net/sourceforge/jnlp/runtime/jar03_dotdotN1.jar: crafted jar with hacked zip entries to be named like ".."
|
|
+ * tests/netx/unit/net/sourceforge/jnlp/runtime/jar_03_dotdot_jarN1.jnlp: jnlp to call jar03_dotdotN1.jar
|
|
+ * netx/net/sourceforge/jnlp/cache/CacheUtil.jsava: (hex) made public to be reused in JNLPClassLoader
|
|
+ * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: if nested jar contains .. in path, is extracted as hashed
|
|
+
|
|
+2019-06-26 Jiri Vanek <jvanek@redhat.com>
|
|
+
|
|
+ Fixed bug when relative path (..) could leak up (even out of cache) - CVE-2019-10182
|
|
+ * netx/net/sourceforge/jnlp/cache/CacheUtil.java: if path or query contains .. is saved to cache via its hash
|
|
+ * netx/net/sourceforge/jnlp/util/FileUtils.java: added warning about different behavior on win/linux
|
|
+ * tests/netx/unit/net/sourceforge/jnlp/cache/CacheUtilTest.java: added tests for hashing
|
|
+ * tests/netx/unit/net/sourceforge/jnlp/runtime/JNLPClassLoaderTest.java: added test for .. in path. Added test
|
|
+ that verifies encoded .. (%2E%2E) do not leak from cahce
|
|
+ * tests/netx/unit/net/sourceforge/jnlp/runtime/up.jnlp: example jnlp with .. full url
|
|
+
|
|
2018-05-14 Jiri Vanek <jvanek@redhat.com>
|
|
|
|
* netx/net/sourceforge/jnlp/runtime/AppletEnvironment.java: getDocumentBase now returns codeBase as fallback when
|
|
diff --git a/tests/netx/unit/net/sourceforge/jnlp/cache/CacheUtilTest.java b/tests/netx/unit/net/sourceforge/jnlp/cache/CacheUtilTest.java
|
|
index 6b0cd256..5dbf2d69 100644
|
|
--- a/tests/netx/unit/net/sourceforge/jnlp/cache/CacheUtilTest.java
|
|
+++ b/tests/netx/unit/net/sourceforge/jnlp/cache/CacheUtilTest.java
|
|
@@ -135,6 +135,14 @@ public class CacheUtilTest {
|
|
File r = CacheUtil.urlToPath(u, "/tmp/");
|
|
Assert.assertEquals(expected, r);
|
|
}
|
|
+
|
|
+ @Test
|
|
+ public void testQueryGotHAshedToo() throws Exception {
|
|
+ final URL u = new URL("https://example2.com/something/my.jar?../../harm");
|
|
+ final File expected = new File("/tmp/https/example2.com/2844b3c690ea355159ed61de6e727f2e9169ab55bf58b8fa3f4b64f6a25bd7.jar");
|
|
+ File r = CacheUtil.urlToPath(u, "/tmp/");
|
|
+ Assert.assertEquals(expected, r);
|
|
+ }
|
|
|
|
|
|
@Test
|
|
diff --git a/tests/netx/unit/net/sourceforge/jnlp/runtime/JNLPClassLoaderTest.java b/tests/netx/unit/net/sourceforge/jnlp/runtime/JNLPClassLoaderTest.java
|
|
index 2b28fb93..d86786ab 100644
|
|
--- a/tests/netx/unit/net/sourceforge/jnlp/runtime/JNLPClassLoaderTest.java
|
|
+++ b/tests/netx/unit/net/sourceforge/jnlp/runtime/JNLPClassLoaderTest.java
|
|
@@ -405,6 +405,8 @@ public class JNLPClassLoaderTest extends NoStdOutErrTest {
|
|
JNLPRuntime.setTrustAll(true);
|
|
JNLPRuntime.setSecurityEnabled(false);
|
|
JNLPRuntime.setDebug(true);
|
|
+ String manifestAttsBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK);
|
|
+ JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, "NONE");
|
|
try {
|
|
final JNLPFile jnlpFile1 = new JNLPFile(new URL("http://localhost:" + port + "/up.jnlp"));
|
|
final JNLPClassLoader classLoader1 = JNLPClassLoader.getInstance(jnlpFile1, UpdatePolicy.ALWAYS, false);
|
|
@@ -419,6 +421,7 @@ public class JNLPClassLoaderTest extends NoStdOutErrTest {
|
|
JNLPRuntime.setTrustAll(trustBackup);
|
|
JNLPRuntime.setSecurityEnabled(securityBAckup);
|
|
JNLPRuntime.setDebug(verbose);
|
|
+ JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, manifestAttsBackup);
|
|
as.stop();
|
|
}
|
|
|
|
@@ -451,6 +454,11 @@ public class JNLPClassLoaderTest extends NoStdOutErrTest {
|
|
JNLPRuntime.setTrustAll(true);
|
|
JNLPRuntime.setSecurityEnabled(false);
|
|
JNLPRuntime.setDebug(true);
|
|
+ //fix of "All files, except signaturre files, are now checked for signatures" make this actually correctly failing ahead of time
|
|
+ String ignoreBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES);
|
|
+ JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES, "true");
|
|
+ String manifestAttsBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK);
|
|
+ JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, "NONE");
|
|
try {
|
|
//it is invalid jar, so we have to disable checks first
|
|
final JNLPFile jnlpFile = new JNLPFile(new URL("http://localhost:" + port + "/jar_03_dotdot_jarN1.jnlp"));
|
|
@@ -488,10 +496,102 @@ public class JNLPClassLoaderTest extends NoStdOutErrTest {
|
|
JNLPRuntime.setTrustAll(trustBackup);
|
|
JNLPRuntime.setSecurityEnabled(securityBAckup);
|
|
JNLPRuntime.setDebug(verbose);
|
|
+ JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES, ignoreBackup);
|
|
+ JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_ENABLE_MANIFEST_ATTRIBUTES_CHECK, manifestAttsBackup);
|
|
as.stop();
|
|
}
|
|
|
|
}
|
|
|
|
+ @Test(expected = Exception.class)
|
|
+ public void testDifferentSignatureInManifestMf() throws Exception {
|
|
+ CacheUtil.clearCache();
|
|
+ int port = ServerAccess.findFreePort();
|
|
+ File dir = FileTestUtils.createTempDirectory();
|
|
+ dir.deleteOnExit();
|
|
+ File jar = new File(dir,"jar03_dotdotN1.jar");
|
|
+ File jnlp = new File(dir,"jar_03_dotdot_jarN1.jnlp");
|
|
+ InputStream is1 = this.getClass().getClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/jar_03_dotdot_jarN1.jnlp");
|
|
+ InputStream is2 = this.getClass().getClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/jar03_dotdotN1.jar");
|
|
+ OutputStream fos1 = new FileOutputStream(jnlp);
|
|
+ OutputStream fos2 = new FileOutputStream(jar);
|
|
+ StreamUtils.copyStream(is1, fos1);
|
|
+ StreamUtils.copyStream(is2, fos2);
|
|
+ fos1.flush();;
|
|
+ fos2.flush();
|
|
+ fos1.close();
|
|
+ fos2.close();
|
|
+ ServerLauncher as = ServerAccess.getIndependentInstance(dir.getAbsolutePath(), port);
|
|
+ boolean verifyBackup = JNLPRuntime.isVerifying();
|
|
+ boolean trustBackup= JNLPRuntime.isTrustAll();
|
|
+ boolean securityBAckup= JNLPRuntime.isSecurityEnabled();
|
|
+ boolean verbose= JNLPRuntime.isDebug();
|
|
+ JNLPRuntime.setVerify(false);
|
|
+ JNLPRuntime.setTrustAll(true);
|
|
+ JNLPRuntime.setSecurityEnabled(false);
|
|
+ JNLPRuntime.setDebug(true);
|
|
+ String ignoreBackup = JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES);
|
|
+ JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES, "false");
|
|
+ try {
|
|
+ //it is invalid jar, so we have to disable checks first
|
|
+ final JNLPFile jnlpFile = new JNLPFile(new URL("http://localhost:" + port + "/jar_03_dotdot_jarN1.jnlp"));
|
|
+ final JNLPClassLoader classLoader = JNLPClassLoader.getInstance(jnlpFile, UpdatePolicy.ALWAYS, false);
|
|
+ } finally {
|
|
+ JNLPRuntime.setVerify(verifyBackup);
|
|
+ JNLPRuntime.setTrustAll(trustBackup);
|
|
+ JNLPRuntime.setSecurityEnabled(securityBAckup);
|
|
+ JNLPRuntime.setDebug(verbose);
|
|
+ JNLPRuntime.getConfiguration().setProperty(DeploymentConfiguration.KEY_SECURITY_ITW_IGNORECERTISSUES, ignoreBackup);
|
|
+ as.stop();
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+ @Test
|
|
+ public void testEncodedPathIsNotDecodedForCache() throws Exception {
|
|
+ CacheUtil.clearCache();
|
|
+ int port = ServerAccess.findFreePort();
|
|
+ File dir = FileTestUtils.createTempDirectory();
|
|
+ dir.deleteOnExit();
|
|
+ dir = new File(dir,"base");
|
|
+ dir.mkdir();
|
|
+ File jar = new File(dir,"j1.jar");
|
|
+ File jnlp = new File(dir+"/a/b/upEncoded.jnlp");
|
|
+ jnlp.getParentFile().mkdirs();
|
|
+ InputStream is = this.getClass().getClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/upEncoded.jnlp");
|
|
+ String jnlpString = StreamUtils.readStreamAsString(is, true, "utf-8");
|
|
+ is.close();
|
|
+ jnlpString = jnlpString.replaceAll("8080", ""+port);
|
|
+ is = this.getClass().getClassLoader().getResourceAsStream("net/sourceforge/jnlp/runtime/j1.jar");
|
|
+ StreamUtils.copyStream(is, new FileOutputStream(jar));
|
|
+ Files.write(jnlp.toPath(),jnlpString.getBytes("utf-8"));
|
|
+ ServerLauncher as = ServerAccess.getIndependentInstance(jnlp.getParent(), port);
|
|
+ boolean verifyBackup = JNLPRuntime.isVerifying();
|
|
+ boolean trustBackup= JNLPRuntime.isTrustAll();
|
|
+ boolean securityBAckup= JNLPRuntime.isSecurityEnabled();
|
|
+ boolean verbose= JNLPRuntime.isDebug();
|
|
+ JNLPRuntime.setVerify(false);
|
|
+ JNLPRuntime.setTrustAll(true);
|
|
+ JNLPRuntime.setSecurityEnabled(false);
|
|
+ JNLPRuntime.setDebug(true);
|
|
+ try {
|
|
+ final JNLPFile jnlpFile1 = new JNLPFile(new URL("http://localhost:" + port + "/upEncoded.jnlp"));
|
|
+ final JNLPClassLoader classLoader1 = JNLPClassLoader.getInstance(jnlpFile1, UpdatePolicy.ALWAYS, false);
|
|
+ InputStream is1 = classLoader1.getResourceAsStream("Hello1.class");
|
|
+ is1.close();
|
|
+ is1 = classLoader1.getResourceAsStream("META-INF/MANIFEST.MF");
|
|
+ is1.close();
|
|
+ Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/0/http/localhost/"+port+"/upEncoded.jnlp").exists());
|
|
+ //be aware; if decoding ever come in play here, thios will leak out of cache folder. Thus harm user system. See fix for " Fixed bug when relative path (..) could leak up (even out of cache)"
|
|
+ Assert.assertTrue(new File(PathsAndFiles.CACHE_DIR.getFullPath()+"/1/http/localhost/"+port+"/%2E%2E/%2E%2E/%2E%2E/base").exists());
|
|
+ } finally {
|
|
+ JNLPRuntime.setVerify(verifyBackup);
|
|
+ JNLPRuntime.setTrustAll(trustBackup);
|
|
+ JNLPRuntime.setSecurityEnabled(securityBAckup);
|
|
+ JNLPRuntime.setDebug(verbose);
|
|
+ as.stop();
|
|
+ }
|
|
+
|
|
+ }
|
|
|
|
}
|
|
diff --git a/tests/netx/unit/net/sourceforge/jnlp/runtime/upEncoded.jnlp b/tests/netx/unit/net/sourceforge/jnlp/runtime/upEncoded.jnlp
|
|
new file mode 100644
|
|
index 00000000..f0658bbc
|
|
--- /dev/null
|
|
+++ b/tests/netx/unit/net/sourceforge/jnlp/runtime/upEncoded.jnlp
|
|
@@ -0,0 +1,15 @@
|
|
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
+<jnlp spec="6.0+" codebase=".">
|
|
+
|
|
+ <information><title>1965</title><vendor>Nemzeti Ado- es Vamhivatal</vendor><offline-allowed/></information>
|
|
+
|
|
+
|
|
+ <resources>
|
|
+ <j2se href="http://java.sun.com/products/autodl/j2se" version="1.8+" />
|
|
+ <!-- absolute url is a must -->
|
|
+ <jar href="http://localhost:8080/%2E%2E/%2E%2E/%2E%2E/base/j1.jar" version="2.0"/>
|
|
+ </resources>
|
|
+
|
|
+ <application-desc main-class="Hello1" />
|
|
+
|
|
+</jnlp>
|