BEA/Oracle WebLogic application server being an enterprise-ready piece of software treats security seriously. One of the symptoms of that is the fact that all sensitive pieces of information like logins, passwords etc. are kept in encrypted form. While browsing through config.xml or boot.properties files you can easily spot them since they are usually prefixed with ‘{3DES}’ string which obviously suggests the encryption algorithm used.
The interesting thing is that with a little bit of efford it’s actually quite easy to extract the decrypted values from config files by using a few undocumented APIs buried in WebLogic itself. Below you will find a simple tool that will output a content of either .xml or .properties configuration file provided as input, replacing all encrypted values with their original content. It works with WebLogic 10 but can be easily adapted for versions 8 and 9 as well (domain directory structure is slightly different between these versions). I wrote it some time ago in order to be able to easily retrieve logins and passwords of development domains that I kept forgetting too often.
Obviously there are many other uses, like configuration management, application server migration tools etc.
You might get worried that since it’s so easy to get to this supposedly safe data then your production environments are endangered. It isn’t so – the decryption mechanism is useless without a file SerializedSystemIni.dat which contains the 3DES key necessary to decrypt the data and is uniqe for every domain. If this file is properly protected from unauthorized access on OS level then have no worries.
(I was going to put here a link to a interesting blog entry on dev2dev.bea.com portal with some insightful comments on this subject but it seems that Dev2Dev has been shut down due to the BEA acquisition by Oracle. I will update this entry if it pops up somewhere else.)
Update: I have noticed that this article is getting quite many views every day – it seems that forgetting domain passwords is more common problem than it seems
. Some users reported issues while processing their configuration files, which often is caused by the poor use of REGEXP in my original code. In order to make it easy to all of us I have prepared a new version of the tool. It uses XPATH to find all XML nodes and attributes containing encrypted data. I hope that this approach is more robust.
import java.util.*;
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) {
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");
}
}
Feel free to comment and improve.
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) {
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");
}
}

[...] Oracle releases BEA Workshop as a free eclipse plugin First saved by meganashley | 1 days ago Decryption of configuration passwords in WebLogic First saved by MewMewIchigogirl | 1 days [...]
Pingback by Recent Faves Tagged With "weblogic" : MyNetFaves — August 13, 2008 @ 5:10 pm
Thanks, I was looking for a way to do this. Cheers!
Comment by Anonymous — August 14, 2008 @ 7:13 pm
When I try to run this on my boot.prperties, I get the following error:
Exception in thread “main” com.rsa.jsafe.JSAFE_InputException: Invalid input length for decryption.Should be a multiple of the block size – 8.
at com.rsa.jsafe.JG_BlockCipher.decryptFinal(Unknown Source)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptBytes(JSafeEncryptionServiceImpl.java:67)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptString(JSafeEncryptionServiceImpl.java:93)
at weblogic.security.internal.encryption.ClearOrEncryptedService.decrypt(ClearOrEncryptedService.java:56)
at WebLogicDecryptor.processLine(WebLogicDecryptor.java:60)
at WebLogicDecryptor.processFile(WebLogicDecryptor.java:45)
at WebLogicDecryptor.run(WebLogicDecryptor.java:33)
at WebLogicDecryptor.main(WebLogicDecryptor.java:28)
————— nested within: ——————
weblogic.security.internal.encryption.EncryptionServiceException – with nested exception:
[com.rsa.jsafe.JSAFE_InputException: Invalid input length for decryption.Should be a multiple of the block size - 8.]
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptBytes(JSafeEncryptionServiceImpl.java:77)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptString(JSafeEncryptionServiceImpl.java:93)
at weblogic.security.internal.encryption.ClearOrEncryptedService.decrypt(ClearOrEncryptedService.java:56)
at WebLogicDecryptor.processLine(WebLogicDecryptor.java:60)
at WebLogicDecryptor.processFile(WebLogicDecryptor.java:45)
at WebLogicDecryptor.run(WebLogicDecryptor.java:33)
at WebLogicDecryptor.main(WebLogicDecryptor.java:28)
Any ideas? I am using Weblogic8.1 sp4.
Thanks,
Comment by Steven — October 23, 2008 @ 6:09 pm
Any idea what’s the length of the 3-DES secret key?
Comment by Willie — October 27, 2008 @ 12:29 am
Hi Steven, that’s rather strange – should not happen assuming that encrypted data has not been corrupted. Since we can not exclude that there is a bug in my code, you might want to execute ces.decrypt(encoded) method with a encrypted copy-pasted value taken from your config file. Please let me know if you succeed.
Other thing is that the earliest version of WebLogic that I run this tool with was 8.1 sp5, so this might have something to do with it, although not very likely.
Comment by Zbigniew Cyktor — October 27, 2008 @ 7:18 pm
Willie, I don’t know but I’d assume that it uses 168 bit key.
Comment by Zbigniew Cyktor — October 27, 2008 @ 7:22 pm
Hi Zbigniew,
Could you please tell me how I can run this tool against a single copy/pasted encrypted value? I am using wrblogic 8.1 sp4. Also, what classpath entries would need to be set for this?
Comment by Steven — November 24, 2008 @ 5:32 pm
Also,
I have now tried this with Weblogic 8.1 SP6 and when I run it against the config.xml in my domain, it spits out the entire config.xml again with all encrypted passwords. It does not decrypt any passwords, just displays the same config.xml with same encrypted passwords. Any ideas?
Comment by Steven — November 24, 2008 @ 5:54 pm
Hi Steven,
Rather strange. Maybe your config.xml is formatted in a way that fools my primitive regexp code, which extracts encrypted values. You can try to bypass it and run something just like this:
ClearOrEncryptedService ces = new ClearOrEncryptedService(SerializedSystemIni.getEncryptionService(domainDir.getAbsolutePath()));
System.out.println(ces.decrypt(encryptedText));
where encryptedText is pasted from your config file (including ‘{3DES}’ prefix!).
I assume that you already figured out the right classpath.
cheers,
Zbigniew
Comment by Zbigniew Cyktor — November 25, 2008 @ 1:41 pm
Found the block size issue. The code doesn’t like the escaping of the ‘=’ to ‘\=’ in the properties files.
I just added
encoded = encoded.replace(“\\”,”");
in the process line method to clear that up. Worked perfectly afterwards.
Thanks,
Jason
Comment by Jason — December 29, 2008 @ 10:45 pm
Jason,
Thanks for bothering to post the solution! I have just updated the code with your change.
cheers,
Zbigniew
Comment by Zbigniew Cyktor — January 7, 2009 @ 1:03 pm
Hi all,
When I am trying to compile the new code, its throwing the following error:
$ /usr/local/ibi/bea/jdk142_05/bin/javac WebLogicDecryptor.java
WebLogicDecryptor.java:60: replace(char,char) in java.lang.String cannot be applied to (java.lang.String,java.lang.String)
encoded = encoded.replace(“\\”,”");
^
1 error
Any suggestions?
Comment by Steven — January 12, 2009 @ 8:12 pm
Hi Guys, looks like this has something to do with the Java version. I compiled it with Java 1.5 and it compiled fine, but when I tried to run it against boot.properties it threw the following error:
Exception in thread “main” java.lang.NoClassDefFoundError: WebLogicDecryptor
I am running it like this:
/opt/java1.5/bin/java WebLogicDecryptor boot.properties
Comment by Steven — January 15, 2009 @ 10:02 pm
ok, got past that error too
Now the last one and I am stumped at this one:
Exception in thread “main” java.lang.NoClassDefFoundError: weblogic/security/internal/encryption/ClearOrEncryptedService
at WebLogicDecryptor.run(WebLogicDecryptor.java:32)
at WebLogicDecryptor.main(WebLogicDecryptor.java:28)
I have my CLASSPATH set like this:
echo $CLASSPATH
/opt/java1.4/lib/tools.jar:/usr/local/ibi/bea/sp4_weblogic81/server/lib/weblogic_sp.jar:/usr/local/ibi/bea/sp4_weblogic81/server/lib/weblogic.jar::/usr/local/ibi/bea/sp4_weblogic81/common/eval/pointbase/lib/pbserver44.jar:/usr/local/ibi/bea/sp4_weblogic81/common/eval/pointbase/lib/pbclient44.jar:/opt/java1.4/jre/lib/rt.jar:/usr/local/ibi/bea/sp4_weblogic81/server/lib/webservices.jar:/usr/local/ibi/bea/jdk142_05/lib/tools.jar:/usr/local/ibi/bea/sp4_weblogic81/server/lib/weblogic_sp.jar:/usr/local/ibi/bea/sp4_weblogic81/server/lib/weblogic.jar::/usr/local/ibi/bea/sp4_weblogic81/common/eval/pointbase/lib/pbserver44.jar
Comment by Steven — January 15, 2009 @ 10:41 pm
Well, I tried to run it on my 8.1 SP6 config.xml file and got a LOT of errors, mostly concering the regular expression. There is a bug that makes it catch 2 strings together if they are on the same line and then the decoding does not work, and there were a few more. But eventually I got it to run
Funny enough, despite taking about 3 hours to do it, it was still easier than trying to the admin here to tell me the password by himself… I also added an “i” parameter to the processLine function, it helps to use conditioned breakpoints and catch it just as it enters the problematic line.
Anyway, here is the updated code. Zbigniew, Thanks for that chunk of code, mate, you really saved me here. Good on ya.
import java.io.*;
import java.util.regex.*;
import weblogic.security.internal.SerializedSystemIni;
import weblogic.security.internal.encryption.ClearOrEncryptedService;
public class WebLogicDecryptor {
protected static final String REGEX_FOR_XML = “\\{3DES\\}[^\"]*”;
protected static final String REGEX_FOR_PROPERTIES = “\\{3DES\\}.*”;
protected boolean isXML;
protected Pattern pattern;
protected ClearOrEncryptedService ces;
public static void main(String[] args) throws Exception {
if (args.length < 2) {
throw new Exception(“Usage: [domainDir] [configFile]“);
}
File domainDir = new File(args[0]);
File configFile = new File(args[1]);
if (!domainDir.exists() || !domainDir.isDirectory() || !configFile.exists() || configFile.isDirectory()) {
throw new Exception(“Files or directories provided as parameters do not exist.”);
}
new WebLogicDecryptor().run(domainDir, configFile);
}
public void run(File domainDir, File configFile) throws Exception {
ces = new ClearOrEncryptedService(SerializedSystemIni.getEncryptionService(domainDir.getAbsolutePath()));
processFile(configFile);
}
public void processFile(File file) throws Exception {
int i=0;
isXML = file.getName().endsWith(“.xml”);
pattern = Pattern.compile(getRegex());
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(processLine(line, ++i));
}
}
finally {
if (in != null) {
in.close();
}
}
}
protected String processLine(String line, int i) {
String result = line;
Matcher m = pattern.matcher(result);
while (m.find()) {
String encoded = result.substring(m.start(), m.end());
encoded = encoded.replace(‘\\’, ”); // see comment #10 below
String decoded = ces.decrypt(encoded);
result = result.replaceFirst(getRegex(), decoded);
m.reset(result);
}
return result;
}
protected String getRegex() {
return isXML ? REGEX_FOR_XML : REGEX_FOR_PROPERTIES;
}
}
Comment by Kobi — March 3, 2009 @ 3:16 pm
Ok, I can’t seem to post the config.xml information so I’ll just strip out the tags
This is what credentials looked like before decryption:
CredentialEncrypted=”{3DES}OlzwOC4caOpQdC//Qf5EeSOFPc7jYnQS7B9UrYS1kto=” Name=”TestDomain”
CredentialEncrypted=”{3DES}M5ZBXGoihvVW6dxdWB8RbPHxvgadUZwbJ9SicB0xXyspQtxaYSEqojoVBTiTD8dZMDBhuFQzb41I4gOJ7NTPT0xBsKd/TUHV”
This is what they looked like after the decryption:
CredentialEncrypted=”0xfb9cbcf181eefc7667877422b0″ Name=”TestDomain”
CredentialEncrypted=”0×19e021ed0f324dc6d2a2c9bf78b062abb099ae45eaecce70311458bfc162deef”
Any clues on what might be the issue here?
Comment by Steven — March 3, 2009 @ 7:59 pm
Kobi, thanks a lot for sharing the improved version! I will update the code with your changes. I guess that the most error-proof version would probably have to be done as a SAX parser to avoid all problems with different ways the config.xmls are formatted.
Steven, it seems that the decryption procedure worked just fine. The trick is that the output is binary data encoded as hexadecimals (as the “0x” prefix suggests). If you are looking for logins/passwords, then they are most likely somewhere deeper in the config.xml.
cheers!
Comment by Zbigniew Cyktor — March 4, 2009 @ 5:39 am
Zbigniew, not sure exactly how a SAX parser will help, since you are looking for attributes that correspond to a specific reg exp… I don’t have a lot of experience with SAX but I hardly remember an opetion that allows you to enumerate and iterate over all the attributes in an XML document that match a specific reg exp… But if I am wrong, I would love to know how to do that because I have a task just like that sometimes later this month and my plan was to write some sort of helper class that does just that by running over all the attributes and matching them to the reg exp… Would love to save myself that work.
I agree with what you said about the hex output. The specific attribute in question is a serialization of a java object (representing Credentials) so the plain output is not very clear to the human eye but it is to a java deserializer. It’s exactly the same mechanism that decrypts passwords (I checked it on JDBC Connection Pool passwords) and it works perfectly. I am still trying to figure out how you found out how to use these undocumented classes in the first place… You the man…
So, again, thanks for the code.
Cheers,
Kobi
Comment by Kobi — March 4, 2009 @ 1:25 pm
The trick is that in case of SAX parsing you don’t need regular expressions at all since it’s easy to find which attribute or element needs to be decrypted – either by checking if its name has ‘Encrypted’ suffix or the content has ‘{3DES}’ prefix.
In case of your planned task it might make more sense to use regexps together with SAX if the logic required to find right pieces of data is more complex than what we are doing here. Maybe it’s also worth to check whether XPATH could be useful to you. I’m pretty sure that in version 1.0 it did not allow regular expressions but maybe it has changed in the meantime. Good luck!
Comment by Zbigniew Cyktor — March 5, 2009 @ 7:30 am
Thanks, actually, I don’t need to use a regexp if there is a way locate all the attributes whose value contain a specific prefix, much like here. I don’t remember seeing an interface for that, but I’ll check again
Cheers,
Comment by Kobi — March 5, 2009 @ 8:06 am
Hi Guys, so to see the clear text password I need a Java deserializer? If not, then how do I convert those Hexadecimals to readable text?
Thanks to both Zbigniew and Kobi for this great utility. It works very well on the boot.properties and shows clear text user/pass. Now if we can get it to do that for config.xml as well….
Comment by Steven — March 5, 2009 @ 7:33 pm
[...] for me, I’ve found this post, he got this working for Weblogic 10, however, the config file structure is a bit different, so I [...]
Pingback by Decryption of Weblogic 8 3DES passwords in config.xml… « Sameh M. Shaker’s Weblog — March 31, 2009 @ 6:31 am
Hi,
I get the below exception when i was trying to run
weblogic.security.internal.encryption.EncryptionServiceException: com.rsa.jsafe.
JSAFE_PaddingException: Could not perform unpadding: invalid pad byte.
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decr
yptBytes(JSafeEncryptionServiceImpl.java:78)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decr
yptString(JSafeEncryptionServiceImpl.java:94)
at weblogic.security.internal.encryption.ClearOrEncryptedService.decrypt
(ClearOrEncryptedService.java:87)
at WebLogicDecryptor.processLine(WebLogicDecryptor.java:68)
at WebLogicDecryptor.processFile(WebLogicDecryptor.java:49)
at WebLogicDecryptor.run(WebLogicDecryptor.java:36)
at WebLogicDecryptor1.main(WebLogicDecryptor1.java:28)
Caused by: com.rsa.jsafe.JSAFE_PaddingException: Could not perform unpadding: in
valid pad byte.
at com.rsa.jsafe.JA_PKCS5Padding.a(Unknown Source)
at com.rsa.jsafe.JG_BlockCipher.decryptFinal(Unknown Source)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decr
yptBytes(JSafeEncryptionServiceImpl.java:68)
… 6 more
Any idea why this happens
Comment by PerfTester — April 1, 2009 @ 9:01 am
How to decrypt suppose if the password starting with {AES}HvuAQSKr5aG….
Comment by senthil — May 13, 2009 @ 2:35 pm
I tried to decrypt a given text by using:
ClearOrEncryptedService ces2 = new ClearOrEncryptedService(SerializedSystemIni.getEncryptionService(domainDir.getAbsolutePath()));
System.out.println(ces2.decrypt(“{3DES}C7IknhvOSWU=”));
I got the following exception any ideas:
com.rsa.jsafe.JSAFE_PaddingException: Could not perform unpadding: invalid pad byte.
at com.rsa.jsafe.JA_PKCS5Padding.performUnpadding(Unknown Source)
at com.rsa.jsafe.JG_BlockCipher.decryptFinal(Unknown Source)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptBytes(JSafeEncryptionServiceImpl.java:67)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptString(JSafeEncryptionServiceImpl.java:93)
at weblogic.security.internal.encryption.ClearOrEncryptedService.decrypt(ClearOrEncryptedService.java:56)
at edu.play.WebLogicDecryptor.run(WebLogicDecryptor.java:40)
at edu.play.WebLogicDecryptor.main(WebLogicDecryptor.java:32)
————— nested within: ——————
weblogic.security.internal.encryption.EncryptionServiceException – with nested exception:
[com.rsa.jsafe.JSAFE_PaddingException: Could not perform unpadding: invalid pad byte.]
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptBytes(JSafeEncryptionServiceImpl.java:77)
at weblogic.security.internal.encryption.JSafeEncryptionServiceImpl.decryptString(JSafeEncryptionServiceImpl.java:93)
at weblogic.security.internal.encryption.ClearOrEncryptedService.decrypt(ClearOrEncryptedService.java:56)
at edu.play.WebLogicDecryptor.run(WebLogicDecryptor.java:40)
at edu.play.WebLogicDecryptor.main(WebLogicDecryptor.java:32)
Comment by Skely — June 19, 2009 @ 6:35 pm
Thank you guys for the wonderful postings, it works.
Comment by Andy — July 3, 2009 @ 12:26 am
Steven,
How did you get around this one?
Exception in thread “main” java.lang.NoClassDefFoundError: weblogic/security/internal/encryption/ClearOrEncryptedService
at WebLogicDecryptor.main(WebLogicDecryptor.java:23)
Thanks.
Comment by Harsha — September 1, 2009 @ 4:42 pm
You just need to add weblogic.jar (which is part of you server installation) to the classpath while running the code.
Comment by Zbigniew Cyktor — September 1, 2009 @ 6:13 pm
This rocks !!!
I had an issue with node.getTextContent(). Probably my xml jars are old. Copied the password part from xml to properties file. It worked. Thanks.
Comment by Mahesh — October 6, 2009 @ 4:04 pm
[...] http://gustlik.wordpress.com/2008/08/06/decryption-of-configuration-passwords-in-weblogic/ [...]
Pingback by Decrypting 3DES in weblogic 8.1 configuration « takie tam dyrdymały — October 26, 2009 @ 12:07 pm