tl;dr

If you you need a customized SSH/SFTP server, Apache Mina SSHD will make it easy for you. This article leverages it for the use case of recovering SFTP passwords from Broadcom’s Automic® Automation (formerly UC4). Check out the Chatty SSHd github repository.

Obfuscation is not encryption

In my current project, I am working with a customer team on modernizing their legacy Automic/UC4 landscape. The product is used for multiple purposes there. Among others:

  • batch orchestration,
  • distributed reliable scheduling and
  • file-based integration with external partners over SFTP.

I might elaborate on our great DSL based approach to standardizing batch workflows and enabling continuous delivery and self-service for Automic/UC4 in another article. This time I want to focus on the SFTP transfers. The canonical way to do SFTP in Automic/UC4 is the Rapid Automation FTP Agent.

The product designers of Automic/UC4 have a weird conception of security. The product is full of idiosyncratic design decisions. It’s a wonder, that it was never featured on Fefes Blog, yet. One of the stranger things is Automic’s use of encryption. Passwords entered into the system (Login objects, SFTP passwords, …) are supposed to be encrypted on storage. If you look closer, they are not encrypted, but only obfuscated. The system can read them without being provided with a secret key. The key seems to be baken into the system. (Furthermore, they use a proprietary encryption scheme. No, not only one! They use multiple different schemes.)

Restoring locked-in passwords

A long, long time ago in a galaxy not so far away, former team members decided that it might be a great idea to keep all SFTP account data in Automic’s database exclusively. Spoiler: It’s not. While you can use the SFTP connection objects without trouble, retrieving the passwords and storing them somewhere else is not possible by default. This is obviously not due to actual security implications; the agent can still recover them. It’s the UI that doesn’t provide this functionality.

Approach 0: Hack Automic

You could now go and start Automic’s application in a debugger, break the algorithm and decrypt the information. It would probably be fun. However, I am afraid of the legal implications. Also, there is a simpler way to expose the obfuscated passwords: Create a dummy SFTP server, that exposes the desired data to you.

Approach 1: Patch OpenSSHd

My first approach was to patch OpenSSHd to make it chatty and log all entered passwords. Read more about it in my followup article “A chatty SSH Server with OpenSSHd”.

In our situation, this approach didn’t work out. Shipping a docker image to our DMZ was impossible. The complete DMZ is still stuck on a good old VM-based infrastructure, with access being limited to unprivileged users. Packaging OpenSSHd differently would be possible but inconvenient.

Approach 2: Create a customized Apache MINA sshd fatjar

I needed a solution which creates dead simple deployables: A single self-contained file, executable as an unprivileged user, to start up our “chatty” SSH server.

At the mentioned customer, I had the choice between 2 technologies: Go and Java. Both feature established SSH/SFTP implementations. For Go you could use SFTPGo or the more low-level crypto/ssh package + pkg/sftp. I didn’t try it, though.

In my example I use Java and Apache Mina SSHD. You can find the full code of chatty-sshd on github.

The app class containing the main method is simple:

package de.metamorphant.examples.chattysshd;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.keyprovider.AbstractGeneratorHostKeyProvider;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.subsystem.SubsystemFactory;
import org.apache.sshd.sftp.server.SftpSubsystemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ChattySshDaemonApp {
	private static final String BIND_ADDRESS = "127.0.0.1";      // only listen to localhost
	private static final int SSHD_PORT = 2224;
	private static Logger logger = LoggerFactory.getLogger(ChattySshDaemonApp.class);

	public static void main(String[] argv) {
		SshServer sshd = SshServer.setUpDefaultServer();
		sshd.setHost(BIND_ADDRESS);
		sshd.setPort(SSHD_PORT);
		
		// If the host key does not exist yet, it will be auto-created
		AbstractGeneratorHostKeyProvider hostKeyProvider = new SimpleGeneratorHostKeyProvider(
		                                                                    Path.of("hostkey.ser"));
		hostKeyProvider.setAlgorithm("RSA");
		sshd.setKeyPairProvider(hostKeyProvider);

		List<SubsystemFactory> namedFactoryList = new ArrayList<SubsystemFactory>();
		namedFactoryList.add(new SftpSubsystemFactory());
		sshd.setSubsystemFactories(namedFactoryList);

		sshd.setPasswordAuthenticator(new LoggingPasswordAuthenticator());

		try {
			logger.info("Starting dummy sshd on bind_address:port " + BIND_ADDRESS + ":" + SSHD_PORT);
			sshd.start();
			while (true) {
				Thread.sleep(2000);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

That’s all the code you need for this little hack. Using the right pom.xml, this is neatly wrapped into a fatjar app. The corresponding LoggingPasswordAuthenticator logs all passwords:

package de.metamorphant.examples.chattysshd;

import org.apache.sshd.server.auth.AsyncAuthException;
import org.apache.sshd.server.auth.password.PasswordAuthenticator;
import org.apache.sshd.server.auth.password.PasswordChangeRequiredException;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoggingPasswordAuthenticator implements PasswordAuthenticator {
	private static Logger logger = LoggerFactory.getLogger(LoggingPasswordAuthenticator.class);

	@Override
	public boolean authenticate(String username, String password, ServerSession session)
			throws PasswordChangeRequiredException, AsyncAuthException {
		logger.debug(String.format("Login attempt by user '%s' with password '%s'\n", username, password));
		return false; // Authentication with our dummy server always fails
	}
}

Don’t forget to configure your log4j2.xml properly and enable log level debug for the LoggingPasswordAuthenticator.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout
        pattern="%d{HH:mm:ss.SSS} %-5level %logger{1.} - %msg%n" />
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="de.metamorphant.examples.chattysshd.LoggingPasswordAuthenticator" level="debug" additivity="false">
      <AppenderRef ref="Console" />
    </Logger>
    <Root level="info">
      <AppenderRef ref="Console" />
    </Root>
  </Loggers>
</Configuration>

Build it and run it:

mvn package
java -jar target/chatty-sshd-0.0.1-SNAPSHOT.jar

When trying to connect with

ssh -p 2224 dummy@localhost

and entering some passwords, you should see something along the lines of

$ java -jar target/chatty-sshd-0.0.1-SNAPSHOT.jar 
WARNING: sun.reflect.Reflection.getCallerClass is not supported. This will impact performance.
23:19:10.141 INFO  d.m.e.c.ChattySshDaemonApp - Starting dummy sshd on bind_address:port 127.0.0.1:2224
23:19:10.148 INFO  o.a.s.c.i.DefaultIoServiceFactoryFactory - No detected/configured IoServiceFactoryFactory using Nio2ServiceFactoryFactory
23:19:40.545 DEBUG d.m.e.c.LoggingPasswordAuthenticator - Login attempt by user 'dummy' with password 'dummypassword'

23:19:42.985 DEBUG d.m.e.c.LoggingPasswordAuthenticator - Login attempt by user 'dummy' with password 'anotherpassword'

Et voilà, your chatty SSH server is ready to restore the freedom of your passwords. Just run it on the same server as your RA FTP Agent and configure your SFTP connections to use host localhost without changing the remaining connection details.

Conclusion

If you were paying attention, you’ll have noticed that this trick can be used to reveal the password of any SSH client connecting with our dummy Apache MINA server. Does it make you feel vulnerable? It should. Go password-less and use public key authentication!

By the way, the same approach can be used to fire up a customized SSH/SFTP server programmatically. For example, this feature is useful when you want to create automatic end-to-end tests for your SFTP integration solutions. Your Apache Mina SSH Server makes a great test double!



Post header background image by Mircea Ploscar from Pixabay.


Contact us