четверг, 11 февраля 2010 г.

Расшифровываем пароли из конфигурациооных файлов WebLogic

Oracle/BEA достаточно серьезно подошла к хранению секретной информации в файлах конфигурации WebLogic Application Server. Если посмотреть config.xml, .*-jdbc.xml или boot.properties, то можно увидеть, что все чувствительные данные, наподобие паролей для подключения к базе данных или хранилищу ключей записаны в шифрованном виде с префиксом '{3DES}'. Можно догадаться, что этот префикс указывает на алгоритм, использованный для шифрования реальных данных. Очевидно, что какой бы алгоритм шифрования не использовался, он должен позволять восстановить исходные данные для того, чтобы передать их во внешнюю систему для которой они предназначены.


Однажды, я задумался, а можно ли восстановить шифрованные данные и что для этого нужно сделать? Мысль эта посетила меня не случайно, так как нужно было отправить конфиг во внешний мир, а знания посторонними людьми некоторых наших паролей не прибавили бы мне душевного равновесия.

Небольшое усилие рук и мозга, и решение было найдено здесь :). У WebLogic AS есть недокументированное внутреннее API для работы информацией, которую нужно кодировать.
Утилита, код которой размещен ниже использует его, позволяя легко получать оригинальные данные из конфигов. Код работает в WebLogic 10 (проверено лично). Для 8 или 9 версии его нужно немного подправить согласно другой структуре папок в домене.

Внимание! Следует учесть, что API использует уникальный для каждого домена файл security/SerializedSystemIni.dat качестве данных для [де]шифрования.

import java.util.*;
import java.io.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import weblogic.security.internal.*; // требуется weblogic.jar
import weblogic.security.internal.encryption.*;

public class WebLogicDecryptor {

    private static final String PREFIX = "{3DES}";
    private static final String XPATH_EXPRESSION = "//node()[starts-with(text(), '" + PREFIX + "')] | //@*[starts-with(., '" + PREFIX + "')]";
    private static ClearOrEncryptedService ces;

    public static void main(String[] args) throws Exception {
        if (args.length < 2) {
            throw new Exception("Usage: [domainDir] [configFile]");
        }
        ces = new ClearOrEncryptedService(SerializedSystemIni.getEncryptionService(new File(args[0]).getAbsolutePath()));
        File file = new File(args[1]);
        if (file.getName().endsWith(".xml")) {
            processXml(file);
        } else if (file.getName().endsWith(".properties")) {
            processProperties(file);
        }
    }

    private static void processXml(File file) throws Exception {
        Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
        XPathExpression expr = XPathFactory.newInstance().newXPath().compile(XPATH_EXPRESSION);
        NodeList nodes = (NodeList)expr.evaluate(doc, XPathConstants.NODESET);
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            print(node.getNodeName(), node.getTextContent());
        }
    }
    
    private static void processProperties(File file) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileInputStream(file));
        for (Map.Entry p : properties.entrySet()) {
            if (p.getValue().toString().startsWith(PREFIX)) {
                print(p.getKey(), p.getValue());
            }
        }
    }

    private static void print(Object attributeName, Object encrypted) {
        System.out.println("Node name: " + attributeName);
        System.out.println("Encrypted: " + encrypted);
        System.out.println("Decrypted: " + ces.decrypt((String)encrypted) + "\n");
    }
}

1 комментарий: