如果你不想用WebLogic密码恢复(一)(http://www.cnblogs.com/alfredxiao/archive/2010/09 /16/weblogic_lost_password.html)介绍的加新帐号的方式,哦们还有一个至强的杀手锏,就是反向破解。废话少说了,这种方 法就是利用WLST脚本对boot.properties文件进行解密。大家都知道,boot.properties就是保存了你的启动帐号和密码的一个 文件,开始时是明文的,第一次启动后被系统加密。当忘记密码之后,用本法可以破解从而读出之前的密码。其中之原理就不得而知了。
# Jython Script for displaying de - crypted WebLogic boot.properties files
#
# To run, change to a WebLogic domain directory and execute:
#
# > / opt / weblogic / wlsadm / weblogic92 / common / bin / wlst.sh ~/ home / chordadm / wlsdecrypt.py (Unix)
# OR
# > C:\\bea\\weblogic92\\common\\bin\\wlst.cmd C:\\myscripts\\wlsdecrypt.py (Windows)
#
# Add parameter ' -? ' to the end of the command line to display more help
# =============================================================================
import os
from java.io import FileInputStream
from java.util import Properties
from weblogic.management import EncryptionHelper
from weblogic.security.service import SecurityManager
from weblogic.security.subject import SubjectManager
#
=============================================================================# Main
# =============================================================================
def main():
# for arg in sys.argv:
# if arg.count(arg.strip()):
# printUsageAndExit()
saltFilePath = os.path.join( ' security ' , ' SerializedSystemIni.dat ' )
if not os.path.exists(saltFilePath):
print " Error: The script must be run from a WebLogic domain direcotry or a directory containing '%s' " % saltFilePath
printUsageAndExit()
try :
open(saltFilePath, ' r ' ).close()
except IOError:
print " Error: The file '%s' is not readable - check file permissions " % saltFilePath
printUsageAndExit()
processBootFiles(os.curdir, descryptPropsFile)
#
=============================================================================# Decrypt (Note, to encrypt just use: EncryptionHelper.encrypt(text))
# =============================================================================
def decrypt(text):
getKernelIdMethod = SecurityManager.getDeclaredMethod( ' getKernelIdentity ' , None)
getKernelIdMethod.accessible = 1
return EncryptionHelper.decrypt(text, getKernelIdMethod.invoke(SecurityManager, None))
#
=============================================================================# Process Boot Files
# =============================================================================
def processBootFiles(rootPath, processFunc):
if not os.path.isdir(rootPath):
return
fileNames = os.listdir(rootPath)
for fileName in fileNames:
path = os.path.join(rootPath, fileName)
if os.path.isfile(path):
if fileName == ' boot.properties ' :
processFunc(path)
elif os.path.isdir(path):
processBootFiles(path, processFunc)
processFunc( " ./boot.properties " )
#
=============================================================================# Decrypt Props File
# =============================================================================
def descryptPropsFile(filepath):
print ' ----- Decrypting %s ----- ' % filepath
try :
properties = Properties()
file = FileInputStream(filepath)
properties.load(file)
file.close()
for entry in properties.entrySet():
print ' %s = %s ' % (entry.key.strip(), java.lang.String(decrypt(entry.value.strip())))
except IOError:
print " Error: Unable to read file '%s' - check file permissions " % filepath
#
=============================================================================# Print Usage And Exit
# =============================================================================
def printUsageAndExit():
print ' wlsdecrypt.py '
print ' ------------- '
print " Jython Script for displaying de-crypted boot.properties files from a WebLogic domain. Before running the script, change directory to the directory that contains a WebLogic domain (or a directory containing 'security/SerializedSystemIni.dat' and one or more associated 'boot.properties' files). Run this script via WLST or directly via the Java/Jython launch command (the latter option requires both 'jython.jar' and 'weblogic.jar' to be added to the classpath). "
print ' Example Usage: '
print ' > /opt/weblogic/wlsadm/weblogic92/common/bin/wlst.sh ~/home/chordadm/wlsdecrypt.py (Unix) '
print ' > C:\\bea\\weblogic92\\common\\bin\\wlst.cmd C:\\myscripts\\wlsdecrypt.py (Windows) '
exit()
#
# Invoke main and end
#
main()
用法很简单,如下:
1、cd到你的域目录;
2、运行 <weblogic_home>\wlserver_10.3\common\bin\wlst.cmd/sh <path_to_script>/your_script.py
注意:
a. 上面给出的脚本是Jyphon语法的脚本,你需要把它保存起来,文件即是上面第2步的参数指向的文件;
b. 以上的脚本是适用于WebLogic 9.x和10.x的,如果要在WebLogic 8中使用,你需要把“saltFilePath=os.path.join('security', 'SerializedSystemIni.dat')”这行中的'security'改为'.'即可;
c. 确保你要解密的boot.properties是在域目录中,如weblogic 9/10的话你可以从servers\<AdminServer>\security下拷贝。
实际上,高人很多阿,有人写了一个Java程序,来解密包括boot.properties和xml配置文件中的密码(如config.xml及jdbc设置的xml文件),我就把其源码给贴出来分享了:
import java.io. * ;
import javax.xml.parsers. * ;
import javax.xml.xpath. * ;
import org.w3c.dom. * ;
import weblogic.security.internal. * ; // requires weblogic.jar in the class path
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 ) {
System.out.println( " Usage: [domainDir] [configFile] " );
return ;
}
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 " );
}
}
这段代码,原则上对WebLogic 8/9/10都可以使用,单因为目录结构稍有不同,可以根据实际需要调整。原链接是 http://gustlik.wordpress.com/2008/08/06/decryption-of-configuration-passwords-in-weblogic/
另外,原来Apache上也有一个类似的东西,原链接为 http://geronimo.apache.org/apidocs/2.0.1/src-html/org/apache/geronimo /converter/bea/Weblogic81Utils.html。内容如下(以下代码把decryptString()改为public了):
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.geronimo.converter.bea;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Properties;
import java.util.Iterator;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLClassLoader;
import java.net.URL;
/**
* Reads information out of the WebLogic domain directory.
* Needs access to the WebLogic JARs in the weblogic81/server/lib directory.
*
* @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
*/
public class Weblogic81Utils {
private final static Pattern ENCRYPTED_STRING = Pattern.compile( " \\\ " \\{\\S + \\}\\S +? \\\ "" );
private Object decoder;
private Method decode;
private Object decrypter;
private Method decrypt;
private File domainDir;
public Weblogic81Utils(String libDirPath, String domainDirPath) {
File libDir = new File(libDirPath);
if ( ! libDir.exists() || ! libDir.canRead() || ! libDir.isDirectory()) throw new IllegalArgumentException( " Bad weblogic lib dir " );
File weblogicJar = new File(libDir, " weblogic.jar " );
File securityJar = new File(libDir, " jsafeFIPS.jar " );
if ( ! weblogicJar.canRead()) throw new IllegalArgumentException( " Cannot find JARs in provided lib dir " );
domainDir = new File(domainDirPath);
if ( ! domainDir.exists() || ! domainDir.canRead() || ! domainDir.isDirectory()) throw new IllegalArgumentException( " Bad domain directory " );
File state = new File(domainDir, " SerializedSystemIni.dat " );
if ( ! state.canRead()) throw new IllegalArgumentException( " Cannot find serialized state in domain directory " );
try {
ClassLoader loader = new URLClassLoader(securityJar.exists() ? new URL[]{weblogicJar.toURL(), securityJar.toURL()} : new URL[]{weblogicJar.toURL()}, Weblogic81Utils. class .getClassLoader());
initialize(loader, state);
} catch (Exception e) {
throw (RuntimeException) new IllegalArgumentException( " Unable to initialize encryption routines from provided arguments " ).initCause(e);
}
}
public Properties getBootProperties() {
File boot = new File(domainDir, " boot.properties " );
FileInputStream bootIn = null ;
try {
bootIn = new FileInputStream(boot);
} catch (FileNotFoundException e) {
return null ;
}
try {
Properties props = new Properties();
props.load(bootIn);
bootIn.close();
for (Iterator it = props.keySet().iterator(); it.hasNext();) {
String key = (String) it.next();
String value = props.getProperty(key);
if (value != null && value.startsWith( " { " )) props.setProperty(key, decryptString(value));
}
return props;
} catch (Exception e) {
return null ;
}
}
public String getConfigXML() throws FileNotFoundException {
File config = new File(domainDir, " config.xml " );
BufferedReader in = new BufferedReader( new FileReader(config));
StringWriter string = new StringWriter();
PrintWriter out = new PrintWriter(string);
String line;
Matcher m = ENCRYPTED_STRING.matcher( "" );
try {
while ((line = in.readLine()) != null ) {
m.reset(line);
int last = - 1 ;
while (m.find()) {
out.print(line.substring(last + 1 , m.start()));
String s = line.substring(m.start(), m.end());
out.print( " \ "" );
out.print(decryptString(s.substring( 1 , s.length() - 1 )));
out.print( " \ "" );
last = m.end() - 1 ;
}
if (last == - 1 ) {
out.println(line);
} else {
if (line.length() > last + 1 ) {
out.print(line.substring(last + 1 ));
}
out.println();
}
out.flush();
}
in.close();
out.close();
} catch (Exception e) {
return null ;
}
return string.getBuffer().toString();
}
private void initialize(ClassLoader loader, File state) throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, ClassNotFoundException, InstantiationException {
byte [] salt = null , key = null ;
FileInputStream in = new FileInputStream(state);
salt = readBytes(in);
int i = in.read();
if (i != - 1 ) {
if (i != 1 ) throw new IllegalStateException();
key = readBytes(in);
}
in.close();
decrypter = getEncryptionService(loader, salt, key);
decoder = loader.loadClass( " weblogic.utils.encoders.BASE64Decoder " ).newInstance();
decode = decoder.getClass().getMethod( " decodeBuffer " , new Class[]{String. class });
decrypt = decrypter.getClass().getMethod( " decryptString " , new Class[]{ byte []. class });
}
private static byte [] readBytes(InputStream in) throws IOException {
int len = in.read();
if (len < 0 )
throw new IOException( " stream is empty " );
byte result[] = new byte [len];
int index = 0 ;
while ( true ) {
if (index >= len) {
break ;
}
int count = in.read(result, index, len - index);
if (count == - 1 )
break ;
index += count;
}
return result;
}
public String decryptString(String string) throws IllegalAccessException, InvocationTargetException {
if (string.indexOf( ' } ' ) > - 1 ) {
string = string.substring(string.indexOf( " } " ) + 1 );
}
return (String) decrypt.invoke(decrypter, new Object[]{decode.invoke(decoder, new Object[]{string})});
}
static Object getEncryptionService(ClassLoader loader, byte salt[], byte key[]) throws NoSuchMethodException, ClassNotFoundException, IllegalAccessException, InvocationTargetException {
String magic = " 0xccb97558940b82637c8bec3c770f86fa3a391a56 " ;
Object factory = loader.loadClass( " weblogic.security.internal.encryption.JSafeEncryptionServiceImpl " ).getMethod( " getFactory " , new Class[ 0 ]).invoke( null , null );
Method getter = factory.getClass().getMethod( " getEncryptionService " , new Class[]{ byte []. class , String. class , byte []. class });
return getter.invoke(factory, new Object[]{salt, magic, key});
}
}
简单编写一个客户端即可调用之,例如:
import java.io. * ;
public class Main {
public static void main(String args[]) {
try {
if ( args == null || args.length < 2 ) {
System.out.println( " Usage: " );
System.out.println( " arg1 = Server/lib or the Directory which has the requried JAR files " );
System.out.println( " arg2 = App Domain or the Directory which has SerializedSystemIni.dat " );
System.out.println( " [arg3] = 3DES hashed password " );
System.exit( 0 );
}
if ( ! new File(args[ 0 ]).exists()) {
System.out.println( " Path [ " + args[ 0 ] + " ] does not exists " );
System.exit( 0 );
}
if ( ! new File(args[ 1 ]).exists()) {
System.out.println( " Path [ " + args[ 1 ] + " ] does not exists " );
System.exit( 0 );
}
String beaDir = args[ 0 ];
String appDir = args[ 1 ];
String hashedPassword = null ;
if (args.length >= 3 ) {
hashedPassword = args[ 2 ];
}
Weblogic81Utils weblogic81Utils = new Weblogic81Utils(beaDir, appDir);
String configXML = weblogic81Utils.getConfigXML();
Properties bootProperties = (Properties) weblogic81Utils.getBootProperties();
System.out.println( " --------------------------------------------------------------------- " );
System.out.println( " boot.properties " + " <username> " + bootProperties.getProperty( " username " ));
System.out.println( " boot.properties " + " <password> " + bootProperties.getProperty( " password " ));
if (hashedPassword != null ) {
String plainTextPassword = weblogic81Utils.decryptString(hashedPassword);
System.out.println(hashedPassword + " == " + plainTextPassword);
}
System.out.println( " --------------------------------------------------------------------- " );
}
catch (Exception e) {
throw (RuntimeException) new IllegalArgumentException( " Unable to initialize encryption routines from provided ar guments " ).initCause(e);
}
} // end of main
}
注意decryptString()本来不是public的。运行时,第一个参数是server/lib对应的目录路径,如C:\bea\wls816 \weblogic81\server\lib;第二个参数是域目录;第三个参数是可选的,你可以从boot.properties或者其他xml里拿到 密码片段然后作为这个参数,如{3DES}g+uYFmHnzJ7jojlRd+SOwg==,注意在boot.properties文件中,有时用\= 代表一个=,这是由于.properties文件的格式要求,你运行以上程序(Main.java)时输入的第三个参数不应该包含'\'号。
另外还有知道,这些程序解密时都需要读取域目录下的一个文件SerializedSystemIni.dat,以作为解密的key使用,因此,不能把一个域中的加密后的字符片段拿到另一个域中去解,那样是解不出来的。