Adam Caudill

Security Leader, Researcher, Developer, Writer, & Photographer

PL/SQL Developer: Nonexistent Encryption

(See here for another issue discovered during this research; Updates over HTTP & Command Execution.)

PL/SQL Developer by Allround Automations has an option to store the user’s logon history with passwords – the passwords are encrypted with a proprietary algorithm. At this point, you should know how this is going to go.

For those that don’t know, PL/SQL Developer is a tool for developers and database administrators to access Oracle – an essential tool in many enterprise environments. Instead of using something that provides some actual security like DPAPI (which itself is far from perfect, as we saw with the UPEK fiasco), they opted to use a proprietary “encryption” algorithm to protect these passwords – making it trivial to recover the passwords for any attacker that can access the preferences file(s).

Some time ago I asked the vendor about the security of the password storage – they are aware of the lack of security, but don’t make it clear to their customers.

From: Allround Automations Support []
Sent: Monday, February 09, 2015 12:37 PM
To: Adam Caudill
Subject: RE: PL/SQL Developer - Password Storage

Hello Adam,

The encryption is proprietary. If a user copies the config file,
the passwords are also copied, so it's not secure.

Marco Kalter
Allround Automations (

The fact that they are aware that it isn’t secure, yet this issue has existed for years – nor made it clear to users what they are risking by activating the option is extremely disappointing. Vendors have a responsibility to protect customer information, and broken features like this completely ignore that.

The Algorithm #

The encryption algorithm is quite simple, primarily consisting of a bit shift and xor – let’s take a closer look at how it works. The ciphertext produced looks like this:


The first group of four digits (2736) is the key – it’s generated based on the system uptime, producing an integer between 0 and 999, then 2,000 is added. This means that the key is has 1,000 possible values, or just under 10 bits. Of course, when you store the key with the encrypted data – key size really doesn’t matter.

After the key at the beginning, each group of four digits represents one byte – this simple code is all that’s needed to encrypt:

for (int i = 0; i < plaintext.Length; i++)
  var mask = plaintext[i] << 4;
  var n = (mask ^ (key + (i + 1)*10)) + 1000;

  ret += Convert.ToString(n).PadLeft(4, '0');

When you encrypt the string user/password@server, here’s what the encrypted data breaks down to:

  • 2736 = Key
  • 4562 = u
  • 4572 = s
  • 4230 = e
  • 4576 = r
  • 3066 = /
  • 4564 = p
  • 4302 = a
  • 4120 = s
  • 4130 = s
  • 4172 = w
  • 4566 = o
  • 4080 = r
  • 4442 = d
  • 4900 = @
  • 4190 = s
  • 4328 = e
  • 4194 = r
  • 4076 = v
  • 4390 = e
  • 4160 = r

The Data #

The login information is stored in an INI-like file called user.prefs – under the headings of [LogonHistory] and [CurrentConnections]; storage of passwords is an option that is turned off by default, though storage of history is turned on by default. All data stored in these sections is encrypted using this method, so the presence of data in these sections does not necessarily mean that passwords are present.

These files can be stored in a number of locations (the latter are more common with older versions of the application):

  • C:\Users\<username>\AppData\Roaming\PLSQL Developer\Preferences\<username>\
  • C:\Program Files\PLSQL Developer\Preferences\<username>\
  • C:\Program Files (x86)\PLSQL Developer\Preferences\<username>\

The data format for the two sections is somewhat different, in [LogonHistory], the data is in the following format:


In [CurrentConnections], the format is <username>,<password>,<server>,,,; the login can also be stored in C:\Users\<username>\AppData\Roaming\PLSQL Developer\PLS-Recovery\*.cfg, in this same format.

This encryption method is also used in other files, though in less predictable locations.

The Proof of Concept #

We have released a proof of concept tool to decrypt these logins, and as is typical, it’s open source. Simply run the executable from the command line, and it will search for the preference files and print any information it’s able to retrieve.

PL/SQL Developer: Password 'Decrypter'
  Copyright 2016 Adam Caudill & Brandon Wilson
  v1.0.0.0 -

Found 1 config files...
Result! 'user/password@server'

You can also pass in the name of a remote machine, and it will attempt to use the administrative (c$) share.

Credit #

Special thanks to my frequent research partner, Brandon Wilson, for his help with this project.

Adam Caudill

Related Posts

  • PL/SQL Developer: HTTP to Command Execution

    While looking into PL/SQL Developer – a very popular tool for working with Oracle databases, to see how it encrypts passwords I noticed something interesting. When testing Windows applications, I make it a habit to have Fiddler running, to see if there is any interesting traffic – and in this case, there certainly was. PL/SQL Developer has an update mechanism which retrieves a file containing information about available updates to PL/SQL Developer and other components; this file is retrieved via HTTP, meaning that an attacker in a privileged network position could modify this file.

  • Ruby + GCM Nonce Reuse: When your language sets you up to fail…

    A couple hours ago, Mike Santillana posted to oss-security about a rather interesting find in Ruby’s OpenSSL library; in this case, the flaw is subtle – so much so that it’s unlikely that anyone would notice it, and it’s a matter of a seemingly insignificant choice that determines if your code is affected. When performing AES-GCM encryption, if you set the key first, then the IV, and you are fine – set the IV first, you’re in trouble.

  • Breaking the NemucodAES Ransomware

    The Nemucod ransomware has been around, in various incarnations, for some time. Recently a new variant started spreading via email claiming to be from UPS. This new version changed how files are encrypted, clearly in an attempt to fix its prior issue of being able to decrypt files without paying the ransom, and as this is a new version, no decryptor was available1. My friends at Savage Security contacted me to help save the data of one of their clients; I immediately began studying the cryptography related portions of the software, while the Savage Security team was busy looking at other portions.

  • Testing for SWEET32 with YAWAST

    Testing for SWEET32 isn’t simple – when the vulnerability was announced, some argued that the best solution was to assume that if a TLS server supported any of the 3DES cipher suites, consider it vulnerable. The problem is, it’s not that simple. On my employer’s corporate blog, I wrote about practical advice for dealing with SWEET32 – and pointed out that there are ways around the vulnerability, and some are quite simple.

  • When Hashing isn’t Hashing

    Anyone working in application security has found themselves saying something like this a thousand times: “always hash passwords with a secure password hashing function.” I’ve said this phrase at nearly all of the developer events I’ve spoken at, it’s become a mantra of sorts for many of us that try to improve the security of applications. We tell developers to hash passwords, then we have to qualify it to explain that it isn’t normal hashing.