Zaciemnione hasła w plikach konfiguracyjnych Websphere Application Server

Ostatnio musiałem ręcznie edytować pliki konfiguracyjne Websphere Application Server. Chodziło konkretnie o security.xml dla serwera. Chciałem podmienić keystore z certyfikatem serwera ponieważ został wgrany wadliwy certyfikat i nawet konsola administracyjna nie działała. Żeby to zrobić trzeba wpisać hasło do keystore. Nie jest to jednak taka prosta sprawa – hasła w security.xml są pozaciemniane. Zakodowane hasła występują w wielu różnych plikach konfiguracyjnych Websphere. Ja chciałem wpisać hasło do pliku z certyfikatem i kluczem dla SSL. Fragment xmla wygląda tak:

<repertoire xmi:id="SSLConfig_1"
alias="host_Node01/DefaultSSLSettings">
<setting xmi:id="SecureSocketLayer_1"
keyFileName="${USER_INSTALL_ROOT}/etc/DummyServerKeyFile.jks"
keyFilePassword="{xor}CDo9Hgw="

Gdzie {xor}CDo9Hgw= jest zakodowanym domyślnym hasłem keystore w WAS “WebAS”. Nie mogłem sobie pozwolić na zostawienie na serwerze produkcyjnym domyślnego hasła (nie mówiąc o keystore z cennym certyfikatem).

Po krótkiej analizie doszedłem do tego jak to rozkodować.  Łańcuch CDo9Hgw= z zakodowanym hasłem WebAS wygląda jak ciąg bajtów zakodowany base 64. Po odkodowaniu otrzymałem taką samą ilość bajtów jak hasło. Ciąg {xor} sugeruje, że została zastosowana suma modulo 2. Ponieważ operacja xor jest odwracalna przexorowałem ten ciąg bajtów z wejściowym hasłem. Okazało się, że wszystkie znaki zostały dodane modulo 2 (xor) do liczby 0x5f. Sprawdziłem swoją teorię na innych serwerach i innych plikach konfiguracyjnych – okazała się słuszna. Napisałem więc dwie małe klasy służące do kodowania i rozkodowywania haseł z plików konfiguracyjnych Websphere Application Server.

public class PassEncoder {
	public static void main(String[] args) {
		if (args.length == 0) {
			System.out.println("Usage: java PassEncoder
<password>");
			return;
		}
		sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
		String passwordStr = args[0];
		char password[] = passwordStr.toCharArray();
		byte buff[] = new byte [password.length];
		for (int i =0; i < password.length; ++i) {
			buff[i] = (byte) (password[i] ^ 0x5f);
		}
		String output = encoder.encode(buff);
		System.out.println(output);
	}
}
public class PassDecoder {
	public static void main(String[] args) {
		if (args.length == 0) {
			System.out.println("Usage: java PassDecoder <encoded_password>");
			return;
		}
		String input = args[0];
		sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder ();
		byte buff[] = null;
		try {
			 buff = decoder.decodeBuffer(input);
		} catch (java.io.IOException e) {
			e.printStackTrace();
			return;
		}
		for (byte b: buff) {
			System.out.print((char)(b ^ 0x5f));
		}
	}
}

Warto zwrócić uwagę na klasy sun.misc.BASE64Decoder oraz sun.misc.BASE64Encoder – to nieudokumentowane klasy w JRE Suna obsługujące kodowanie base 64. Swoje klasy nazwałem PassEncoder oraz PassDecoder bo (jak widać) sposób zaciemnienia w plikach konfiguracyjnych WAS można nazwać kodowaniem, ale na pewno nie szyfrowaniem. Chroni on jedynie przed szybkim przeczytaniem i zapamiętaniem poufnych haseł.

Zacheusz

Komentarze

Chcesz coś napisać?





*