Skip to content

Commit

Permalink
[SECURITY-3333]
Browse files Browse the repository at this point in the history
  • Loading branch information
kuisathaverat authored and daniel-beck committed Feb 29, 2024
1 parent a61b579 commit 58da751
Show file tree
Hide file tree
Showing 9 changed files with 361 additions and 7 deletions.
35 changes: 35 additions & 0 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,38 @@ Please feel free to contact us. We welcome feedback of any kind!
Contact: support@trilead.com or go to the public forum at http://www.trilead.com

Zurich, March 2008

## Algorithm filters

The algorithm filters can be used to restrict the algorithms that are used by the library.
The filters will remove the algorithms you specify from the SSH algorithms negotiation between client and server.
The library supports the following algorithm filters:
* Kex (Key Exchange) algorithm filter
* Host Key algorithm filter
* Encryption algorithm filter
* MAC algorithm filter

To filter algorithms enable the filters using the following System properties:


* com.trilead.ssh2.jenkins.FilterKexAlgorithms.enabled (default: true)
* com.trilead.ssh2.jenkins.FilterHostKeyAlgorithms.enabled (default: true)
* com.trilead.ssh2.jenkins.FilterMacAlgorithms.enabled (default: true)
* com.trilead.ssh2.jenkins.FilterEncrytionAlgorithms.enabled (default: true)

The algorithms are specified as a comma separated list of algorithm names.
To configure the algorithm filters, use the following System properties:

* com.trilead.ssh2.jenkins.FilterKexAlgorithms.algorithms
* com.trilead.ssh2.jenkins.FilterHostKeyAlgorithms.algorithms
* com.trilead.ssh2.jenkins.FilterMacAlgorithms.algorithms
* com.trilead.ssh2.jenkins.FilterEncrytionAlgorithms.algorithms

Example
```bash
java -Dcom.trilead.ssh2.jenkins.FilterKexAlgorithms.enabled=true \
-Dcom.trilead.ssh2.jenkins.FilterKexAlgorithms.algorithms=diffie-hellman-group-exchange-sha256 \
-jar jenkins.war
```

To check the algorithms filtered by the library, check the `Filter*` classes at the package [`com.trilead.ssh2.jenkins`](src/com/trilead/ssh2/jenkins).
18 changes: 11 additions & 7 deletions src/com/trilead/ssh2/crypto/CryptoWishList.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

import com.trilead.ssh2.crypto.cipher.BlockCipherFactory;
import com.trilead.ssh2.crypto.digest.MessageMac;
import com.trilead.ssh2.jenkins.FilterEncrytionAlgorithms;
import com.trilead.ssh2.jenkins.FilterHostKeyAlgorithms;
import com.trilead.ssh2.jenkins.FilterKexAlgorithms;
import com.trilead.ssh2.jenkins.FilterMacAlgorithms;
import com.trilead.ssh2.transport.KexManager;


Expand All @@ -14,10 +18,10 @@
*/
public class CryptoWishList
{
public String[] kexAlgorithms = KexManager.getDefaultKexAlgorithmList();
public String[] serverHostKeyAlgorithms = KexManager.getDefaultServerHostkeyAlgorithmList();
public String[] c2s_enc_algos = BlockCipherFactory.getDefaultCipherList();
public String[] s2c_enc_algos = BlockCipherFactory.getDefaultCipherList();
public String[] c2s_mac_algos = MessageMac.getMacs();
public String[] s2c_mac_algos = MessageMac.getMacs();
}
public String[] kexAlgorithms = FilterKexAlgorithms.filter(KexManager.getDefaultKexAlgorithmList());
public String[] serverHostKeyAlgorithms = FilterHostKeyAlgorithms.filter(KexManager.getDefaultServerHostkeyAlgorithmList());
public String[] c2s_enc_algos = FilterEncrytionAlgorithms.filter(BlockCipherFactory.getDefaultCipherList());
public String[] s2c_enc_algos = FilterEncrytionAlgorithms.filter(BlockCipherFactory.getDefaultCipherList());
public String[] c2s_mac_algos = FilterMacAlgorithms.filter(MessageMac.getMacs());
public String[] s2c_mac_algos = FilterMacAlgorithms.filter(MessageMac.getMacs());
}
105 changes: 105 additions & 0 deletions src/com/trilead/ssh2/jenkins/FilterAlgorithms.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.trilead.ssh2.jenkins;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.trilead.ssh2.log.Logger;

/**
* Class for filtering algorithms.
* The reason for this filter is that some algorithms have security issues.
* The filter can be disabled by setting the system property {@link #isEnabledFilterProperty} to false.
* The list of algorithms to filter can be set by setting the system property {@link #filteredAlgorithmsProperty}.
*/
public class FilterAlgorithms {
/**
* The system property suffix to enable/disable the filter.
*/
private static final String ALGORITHMS = ".algorithms";
/**
* The system property suffix to set the list of algorithms to filter.
*/
private static final String ENABLED = ".enabled";
/**
* The logger.
*/
private static final Logger LOGGER = Logger.getLogger(FilterAlgorithms.class);
/**
* The system property to enable/disable the filter.
*/
private final String isEnabledFilterProperty;
/**
* The system property to set the list of algorithms to filter.
*/
private final String filteredAlgorithmsProperty;

/**
* The list of algorithms to filter.
*/
private List<String> filteredAlgorithms = new ArrayList<>();

/**
* Constructor.
* @param clazz the class name used for the system properties
* @param filteredAlgorithms the list of algorithms to filter
*/
public FilterAlgorithms(String clazz, List<String> filteredAlgorithms) {
this.filteredAlgorithms = filteredAlgorithms;
this.isEnabledFilterProperty = clazz + ENABLED;
this.filteredAlgorithmsProperty = clazz + ALGORITHMS;
}

/**
* Filter algorithms.
* @param algorithms the algorithms to filter
* @return the filtered algorithms
*/
public String[] filter(String[] algorithms) {
String[] ret = Collections.emptySet().toArray(new String[0]);
if (algorithms != null) {
if (!isEnabled()) {
LOGGER.log(20, "Algorithms filter is disabled");
ret = algorithms;
} else {
ret = Arrays.stream(algorithms)
.filter(x -> !getFilteredAlgorithms().contains(x))
.toArray(String[]::new);
}
} else {
LOGGER.log(20, "Algorithms is null");
}
return ret;
}

/**
* Check if the filter is enabled.
* @return true if the filter is enabled
*/
private boolean isEnabled() {
return Boolean.parseBoolean(System.getProperty(isEnabledFilterProperty, "true"));
}

/**
* Get the list of algorithms to filter.
* @return the list of algorithms to filter
*/
private List<String> getFilteredAlgorithms() {
List<String> ret = new ArrayList<>();
if (System.getProperty(filteredAlgorithmsProperty) != null && !System.getProperty(filteredAlgorithmsProperty).isEmpty()) {
ret = Arrays.asList(System.getProperty(filteredAlgorithmsProperty).split(","));
} else {
ret = filteredAlgorithms;
}
return ret;
}

public String getIsEnabledFilterProperty() {
return isEnabledFilterProperty;
}

public String getFilteredAlgorithmsProperty() {
return filteredAlgorithmsProperty;
}
}
33 changes: 33 additions & 0 deletions src/com/trilead/ssh2/jenkins/FilterEncrytionAlgorithms.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.trilead.ssh2.jenkins;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import com.trilead.ssh2.log.Logger;

/**
* Filter encryption algorithms.
* The reason for this filter is that some algorithms have security issues.
* The filter can be disabled by setting the system property
* com.trilead.ssh2.jenkins.FilterEncrytionAlgorithms.enabled to false.
* The list of algorithms to filter can be set by setting the system property
* com.trilead.ssh2.jenkins.FilterEncrytionAlgorithms.algorithms (e.g. type01,type02,type03).
*/
public class FilterEncrytionAlgorithms {
/*
* The list of algorithms to filter by default.
*/
private static final List<String> filteredAlgorithms = Collections.emptyList();

/**
* Filter algorithms.
* @param algorithms The algorithms to filter.
* @return The filtered algorithms.
*/
public static String[] filter(String[] algorithms) {
FilterAlgorithms filter = new FilterAlgorithms(FilterEncrytionAlgorithms.class.getName(), filteredAlgorithms);
return filter.filter(algorithms);
}
}
32 changes: 32 additions & 0 deletions src/com/trilead/ssh2/jenkins/FilterHostKeyAlgorithms.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.trilead.ssh2.jenkins;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.trilead.ssh2.log.Logger;

/**
* Filter host key algorithms.
* The reason for this filter is that some algorithms have security issues.
* The filter can be disabled by setting the system property
* com.trilead.ssh2.jenkins.FilterHostKeyAlgorithms.enabled to false.
* The list of algorithms to filter can be set by setting the system property
* com.trilead.ssh2.jenkins.FilterHostKeyAlgorithms.algorithms (e.g. type01,type02,type03).
*/
public class FilterHostKeyAlgorithms {
/*
* The list of algorithms to filter.
*/
private static final List<String> filteredAlgorithms = Collections.emptyList();

/**
* Filter algorithms.
* @param algorithms The algorithms to filter.
* @return The filtered algorithms.
*/
public static String[] filter(String[] algorithms) {
FilterAlgorithms filter = new FilterAlgorithms(FilterHostKeyAlgorithms.class.getName(), filteredAlgorithms);
return filter.filter(algorithms);
}
}
34 changes: 34 additions & 0 deletions src/com/trilead/ssh2/jenkins/FilterKexAlgorithms.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.trilead.ssh2.jenkins;

import java.util.ArrayList;
import java.util.List;

import com.trilead.ssh2.log.Logger;

/**
* Filter KEX algorithms.
* The reason for this filter is that some algorithms have security issues.
* The filter can be disabled by setting the system property
* com.trilead.ssh2.jenkins.FilterKexAlgorithms.enabled to false.
* The list of algorithms to filter can be set by setting the system property
* com.trilead.ssh2.jenkins.FilterKexAlgorithms.algorithms (e.g. type01,type02,type03).
*/
public class FilterKexAlgorithms {
/*
* The list of algorithms to filter.
*/
private static final List<String> filteredAlgorithms = new ArrayList<>(
List.of(
// Terrapin attack see https://en.wikipedia.org/wiki/Terrapin_attack
"chacha20-poly1305@openssh.com"));

/**
* Filter algorithms.
* @param algorithms The algorithms to filter.
* @return The filtered algorithms.
*/
public static String[] filter(String[] algorithms) {
FilterAlgorithms filter = new FilterAlgorithms(FilterKexAlgorithms.class.getName(), filteredAlgorithms);
return filter.filter(algorithms);
}
}
36 changes: 36 additions & 0 deletions src/com/trilead/ssh2/jenkins/FilterMacAlgorithms.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.trilead.ssh2.jenkins;

import java.util.ArrayList;
import java.util.List;

import com.trilead.ssh2.log.Logger;

/**
* Filter host key algorithms.
* The reason for this filter is that some algorithms have security issues.
* The filter can be disabled by setting the system property
* com.trilead.ssh2.jenkins.FilterHostKeyAlgorithms.enabled to false.
* The list of algorithms to filter can be set by setting the system property
* com.trilead.ssh2.jenkins.FilterHostKeyAlgorithms.algorithms (e.g. type01,type02,type03).
*/
public class FilterMacAlgorithms {
/*
* The list of algorithms to filter.
*/
private static final List<String> filteredAlgorithms = new ArrayList<>(
List.of(
// Terrapin attack see https://en.wikipedia.org/wiki/Terrapin_attack
"hmac-sha2-512-etm@openssh.com",
// Terrapin attack see https://en.wikipedia.org/wiki/Terrapin_attack
"hmac-sha2-256-etm@openssh.com"));

/**
* Filter algorithms.
* @param algorithms The algorithms to filter.
* @return The filtered algorithms.
*/
public static String[] filter(String[] algorithms) {
FilterAlgorithms filter = new FilterAlgorithms(FilterMacAlgorithms.class.getName(), filteredAlgorithms);
return filter.filter(algorithms);
}
}
1 change: 1 addition & 0 deletions src/com/trilead/ssh2/transport/KexManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ public static String[] getDefaultKexAlgorithmList()
"diffie-hellman-group14-sha1", "diffie-hellman-group1-sha1","ecdh-sha2-nistp256","ecdh-sha2-nistp384","ecdh-sha2-nistp521","curve25519-sha256","curve25519-sha256@libssh.org" };
}

// FIXME this code is not used, the check it makes does not match the implementation in other places.
public static void checkKexAlgorithmList(String[] algos)
{
for (String algo : algos) {
Expand Down
74 changes: 74 additions & 0 deletions test/com/trilead/ssh2/jenkins/FilterAlgorithmsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.trilead.ssh2.jenkins;

import static org.junit.Assert.assertArrayEquals;

import java.util.Arrays;

import org.junit.After;
import org.junit.Test;

public class FilterAlgorithmsTest {

@After
public void setUp() {
System.setProperty("foo.enabled", "true");
System.setProperty("foo.algorithms", "");
}

@Test
public void testFilter() {
String[] kexAlgorithms = {"algorithm0", "algorithm2", "algorithm3"};
String[] expected = {"algorithm2", "algorithm3"};
String[] filteredAlgorithms = {"algorithm0"};
FilterAlgorithms filter = new FilterAlgorithms("foo",Arrays.asList(filteredAlgorithms));

assertArrayEquals(expected, filter.filter(kexAlgorithms));
}

@Test
public void testFilterWithNull() {
String[] expected = {};
FilterAlgorithms filter = new FilterAlgorithms("foo",null);

assertArrayEquals(expected, filter.filter(null));
}

@Test
public void testFilterWithEmptyArray() {
String[] kexAlgorithms = {};
String[] expected = {};
FilterAlgorithms filter = new FilterAlgorithms("foo", Arrays.asList(kexAlgorithms));

assertArrayEquals(expected, filter.filter(kexAlgorithms));
}

@Test
public void testDisabledFilter() {
String[] kexAlgorithms = {"algorithm0", "algorithm2", "algorithm3"};
FilterAlgorithms filter = new FilterAlgorithms("foo", Arrays.asList(kexAlgorithms));
System.setProperty(filter.getIsEnabledFilterProperty(), "false");

assertArrayEquals(kexAlgorithms, filter.filter(kexAlgorithms));
}

@Test
public void testFilterWithEmptyList() {
String[] kexAlgorithms = {"algorithm0", "algorithm2", "algorithm3"};
String[] expected = {};
FilterAlgorithms filter = new FilterAlgorithms("foo", Arrays.asList(kexAlgorithms));
System.setProperty(filter.getFilteredAlgorithmsProperty(), "");

assertArrayEquals(expected, filter.filter(kexAlgorithms));
}

@Test
public void testFilterWithCustomList() {
String[] kexAlgorithms = {"algorithm0", "algorithm2", "algorithm3"};
String[] expected = {"algorithm0"};
FilterAlgorithms filter = new FilterAlgorithms("foo", Arrays.asList(kexAlgorithms));
System.setProperty(filter.getFilteredAlgorithmsProperty(), "algorithm2,algorithm3");

assertArrayEquals(expected, filter.filter(kexAlgorithms));
}

}

0 comments on commit 58da751

Please sign in to comment.