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 0×5f. 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ł.
Komentarze
Chcesz coś napisać?