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.

The Code

The code that really matters is in a PHP file2, named after the Bitcoin address that the victim is to pay the ransom to, and stored under the user’s %TEMP% directory. Here’s the bit that matters to us:

There are some important things that we see immediately:

  • They generate a unique encryption key for each file.
  • They are using AES-128 in ECB mode.
  • They are using RSA to encrypt the AES-128 key and store it in a .db file (also named after the Bitcoin address).
  • They encrypt the first 2,048 bytes of the file, and then replace it with random data.
  • The .db file contains the path, encrypted AES-128 key, and the encrypted data removed from the file.

The Critical Mistake(s)

If you’ve been to any of my talks on cryptography, you should see an immediate issue with this code. If not, let me point this line out:

This line creates a 128 byte key to be used to encrypt the file (it seems the developers don’t know bits from bytes), using PHP’s mt_rand function. This function generates random numbers using the Mersenne Twister algorithm, which happens to use a small (32-bit) seed – this is where the fun begins.

Because of this small seed, if we can observe the initial output of mt_rand, we can brute-force the seed and then predict its future output. Thankfully, the developers of Nemucod made this easy for us. If you recall, the first 2,048 bytes of each file are replaced with random data from mt_rand, then the encryption key is generated immediately after. This means that they have given us everything we need.

Using the first few bytes (4 or 5), we can brute-force the seed that mt_rand used3, and by running mt_rand the appropriate number of times, we can create the exact output that the PHP script did when it encrypted the files, revealing the file encryption keys and allowing us to decrypt all of the files.

Cracking the Seed

To get the seed, we need to brute-force all 2^32 possible values, thankfully there’s a handy tool to do this – and do it within a matter of seconds. A few years ago the always impressive Solar Designer released just what we need. This is a simple command-line tool that takes output (in this case the first few bytes of the first file encrypted) and provides the seed that was used.

Using php_mt_seed, it takes only about a minute to test all of the possible seeds, and identify the correct one. Once we have that, decryption is simple, and we have all of the data back without paying a single cent to the extortionists.

Why Randomness Matters

When it comes to key generation (and many other aspects of cryptography), the use of a secure random number generator is critical. If you look at the documentation for mt_rand, you’ll see this very clear warning:

This function does not generate cryptographically secure values, and should not be used for cryptographic purposes. If you need a cryptographically secure value, consider using random_int(), random_bytes(), or openssl_random_pseudo_bytes() instead.

Had the developers heeded this warning, and used a more appropriate method for generating the file encryption keys, this method would not have worked. Had the developers not been so kind as to provide us with output from mt_rand in the files, this would not have worked. It is the developers of Nemucod that made recovering the data trivial, due to the lack of understanding of proper secure techniques4. While I don’t want to aid ransomware authors, this is a well known aspect of cryptography – if you write crypto code without a full understanding of what you are doing, and what you are using, this is what happens.

  1. In the hours before this post was published, Emsisoft released a decryption tool for those hit by this version of Nemucod. 
  2. This ransomware targets Windows users, though the core is written in PHP. The downloader, written in JavaScript, downloads the Windows version of PHP (version 5.6.3) and uses that to execute the PHP file. Yes, this is as crazy as it sounds. 
  3. If mt_rand is not seeded explicitly via mt_srand, PHP will select a random seed, and seed it automatically. In this case, the developers did not explicitly select a seed. 
  4. There may be additional methods here that could be used, but those are beyond the scope of this article. 

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.

This file is retrieved each time the application starts, and if a version listed in the file is greater than the version installed, the user will be prompted to upgrade (default behavior; otherwise user not prompted until they select Help | Check Online Updates). They have the following options:

  • Update: If a URL is provided, the application will download a file (also over HTTP), and apply the update. If no URL is provided, the option is not presented to the user.
  • Download: Executes the URL provided, so that the user’s browser will open, and immediately download the file. This is typically an executable (*.exe); as is the case elsewhere, the file is retrieved over HTTP, and no validation is being performed.
  • Info: If a URL, it’s executed so that the user’s browser opens to the specified URL; otherwise content is displayed in a message box.

The are (at least) two issues here:

  • Redirect to malicious download; as the user is likely unaware that they shouldn’t trust the file downloaded as a result of using the Download option, an attacker could replace the URL and point to a malicious file, or simply leverage their privileged position to provide a malicious file at the legitimate URL.
  • Command Execution; when the user selects the Download option, the value in the file is effectively ShellExecute’d, without any validation – there is no requirement that it be a URL. If a command is inserted, it will be executed in the context of the user.

This means that a user believing that they are downloading an update, can actually be handing full control over to an attacker – this is a case where not bothering to use HTTPS to secure traffic, can provide multiple methods for an attacker to gain control of the user’s PC. This is a great example of the importance of using HTTPS for all traffic – it’s not just about privacy, it’s also critical for integrity.

The tested version of PL/SQL Developer was 11.0.4, though the issue likely well predates that version. The vendor reports that this issue has been addressed by enforcing HTTPS on their website, and application changes made in version 11.0.6. It is recommended that all users update to the latest version.

Vulnerability Note: VU#229047
CVE: CVE-2016-2346

Technical Details

The update file is retrieved from – the request issued by the application looks like this:

Here’s what a response looks like – it’s a INI-like file, the Download value is the item we care about most here:

By changing the returned file, replacing this line:


With this:


When the user selects the Download option, calc.exe will be executed.

Here is an example of a pls.updates file that demonstrates this flaw (the key changes are increasing the Version, so that the user will see it as an update, clearing the Update value, so the only option is Download, and setting Download to the command that you wish to be executed):

Special Thanks

Thanks to Garret Wassermann of CERT/CC for his assistance and Allround Automations for addressing the issue.

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.

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:

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.

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


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

Verizon Hum Leaking Credentials

or, Christmas Infosec Insanity…

A friend mentioned Hum by Verizon, a product that I hadn’t heard of but quickly caught my attention – both from a “here’s a privacy nightmare” perspective, and “I might actually use that” perspective. While looking at the site, I decided to take a look at the source code for the shopping page – what I saw was rather unexpected.

Near the top is a large block of JSON assigned to an otherwise unused variable named phpvars – included was some validation code, a number of URLs, some HTML, and the like. After seeing the first element, isDeveloperMode, I was sure this was worth a closer look.

A few lines in, I ran across something that I would have never expected from a company like Verizon:

Username, password. Embedded in JavaScript. Seriously.

In the JSON, there are several API endpoints listed, from a variety of domains (only one of which is publicly resolvable):


If any of these endpoints would allow an outside attacker to gather private data, I couldn’t say.

There are a few things about this that really surprise me:

  • How did Verizon allow this to go live?
  • Why aren’t they doing any type of post-deployment testing?
  • Weblogic12 – Seriously? Is that really an acceptable password?

The use of stolen and/or misused credentials (user name/passwords) continues to be the No. 1 way to gain access to information. Two out of three breaches exploit weak or stolen passwords, making a case for strong two-factor authentication. – Verizon Data Breach Investigations Report

I’ve reached out to Verizon via Twitter to ensure that they are aware that this information is being leaked. I attempted to email both and – neither of which are valid addresses (another surprise from a company that should have a clue).

Dovestones Software AD Self Password Reset (CVE-2015-8267)

Software AD Self Password Reset v3.0 by Dovestones Software contains a critical vulnerability in the password change functionality, that allows unauthenticated users to change the password of arbitrary accounts.

The vendor has been working with customers to upgrade them to a fixed version.

The /Reset/ChangePass function doesn’t validate that the validation questions have been answered, or validate that the account in question is enrolled. This allows an attacker to reset any account that the service account is able to reset, even if they aren’t enrolled.

The PasswordReset.Controllers.ResetController.ChangePasswordIndex() method in PasswordReset.dll fails to properly validate the user, and performs the password reset on arbitrary accounts.


Successful response:

VU#757840 – Dovestones Software AD Self Password Reset fails to properly restrict password reset request to authorized users

CVE: CVE-2015-8267

access control


Dovestones Software AD Self Password Reset fails to properly validate users, which enables an unauthenticated attacker to reset passwords for arbitrary accounts.


CWE-284: Improper Access Control – CVE-2015-8267

Dovestones Software AD Self Password Reset contains a vulnerable method PasswordReset.Controllers.ResetController.ChangePasswordIndex() in PasswordReset.dll that fails to validate the requesting user. An attacker can reset passwords for arbitrary accounts by manipulating web application requests that call the vulnerable method.


A remote, unauthenticated attacker can reset passwords for arbitrary accounts where usernames are known or can be guessed.


Apply an update

The vendor has worked directly with customers to apply updates for this and other vulnerabilities. Users who have not received an update are encouraged to contact the vendor.



Thanks to Adam Caudill for reporting this vulnerability.

This document was written by Joel Land.

Special thanks to Dovestones for their quick response, and US CERT for their help in coordinating disclosure.