Are You Vulnerable to Memory Scraping? (And What to Do About It)

Originally published here.

The Target breach that first made news in late 2013 was facilitated using “memory scraping malware” called “BlackPOS” or “TrackR” running on the Point of Sale (POS) systems. While many pundits have given Target a hard time, claiming they were misconfigured or that PCI compliance did not result in adequate security for cardholders, the truth is sensitive data having permanence in memory is a very prevalent problem affecting many types of point of sale systems. Worse yet, there is no quick and easy solution.

Consider the following typical diagram of a brick-and-mortar retailer’s credit card flow:

Card Reader -> POS Terminal -> POS Server -> Bank

Conventional wisdom dictates encrypting credit card numbers in transit between hops and while at rest in the POS transaction logs and database. But what happens as the card number is being encrypted? It lives unencrypted in a device’s memory for some period of time, which could be a few CPU cycles or maybe several minutes or even hours. Don’t believe that? Give this a try on your Windows based POS terminal before a transaction:

C:\procdump.exe -ma “POS.exe” -n 30 -t 1

You’ll need to fetch procdump.exe from Microsoft’s SysInternals website. Of course, if your POS terminal’s process name isn’t POS.exe or if it has more than one process running (check in the Windows task manager), then update the above command accordingly. You’ll have 30 seconds to complete a credit card transaction since that command takes a snapshot of memory once per second for 30 seconds.

If you aren’t sure of the process name or how widespread the littering of credit card numbers in RAM really is, an alternative method would be to use mdd to extract all of the memory the Windows machine to a file:

C:\mdd_1.3.exe -o memory.dmp

If you can’t test an actual POS system, then you can use the following simple command line mock-up in C# to demonstrate the same principles:

It’s just a simple command line app that asks for a credit card number. Giving it a test Visa card number looks like this:

After the transaction and process or memory dump are complete, run the following command to attempt to identify potential credit card numbers in the data you collected:

C:\grep.exe -aoE “[0–9]{16}” *.dmp

Grep.exe for Windows can be found from its open source project page. This is a simple 16-digit numerical regular expression search, which may identify false positives, but it will prove the point. For sophistication, run the grep output through a Luhn check (a.k.a. Mod 10) to determine which results are valid credit card number patterns.

Or to home in on the exact test Visa card, try just this:

C:\grep.exe -ao “4111111111111111” *.dmp

With the mocked up C# program, grep finds two instances of the credit card number on the heap:

Code Mechanics

In most programming languages, a “string” of text containing a credit card number is allocated on the process’s memory heap at runtime, and until something specifically de-allocates that memory and overwrites it, the values will remain present. The following diagram is a general example of the virtual memory layout:

In many high-level languages, such as .NET or Java, strings are “immutable,” which means they are never allowed to change at runtime. Updating a string (e.g. concatenating new characters) allocates new memory on the heap with the updated version of the string, while the old copy remains until de-allocation. Passing a string into functions in other layers of code can increase the exposure by allocating an additional copy of that string in the heap for the upstream function to process. Consider the following pseudo-stack trace:

ReceiveSerialMessage(byte[] bytes);

GetCreditCardObj(string Track1, string Track2);

PrepareEncryptedCcTrans(CreditCard creditCard);

EncryptString(string s);

RijndaelManaged(byte[] bytes, AesKey key, InitializationVector iv);

Each layer has at least one copy of the credit card data in memory at any given point in time. Even if your POS immediately encrypts sensitive data, the plaintext version is temporarily floating around on the heap.

In most high-level languages, removing data from memory after de-allocation is dependent upon the “garbage collector.” The garbage collector is the process that tells the Operating System that the memory address space once holding the string containing a credit card number can officially be reused. Garbage collection isn’t immediate. It runs at intervals controlled by the Java or .NET runtime environment, further increasing the exposure of the credit card number on the heap. In the diagram below, imagine the red boxes in Step 2 as credit card data no longer needed by a point-of-sale system. From the point the data is marked for deletion in Step 2 and until the memory is overwritten in Step 4, the credit card data is ripe for scraping.

Lower level (bare metal) programming languages that use pointer arithmetic, such as C/C++, may only keep a single copy in memory, but for how long? The answer is dependent upon how the programmers manage those memory locations. Does the code immediately overwrite the values or are the pointers simply tossed aside leaving the data in the heap until that location is reallocated?

End-to-End Encryption

“End-to-end encryption” of credit cards starting at the card swipe device assures the plaintext credit card data only lives in the memory of the card swipe device. The general purpose computing hardware which runs the POS terminal programs will only ever have the encrypted credit card value in its memory. This is a great way to reduce the exposure, but it is not perfect. Can a retail business operate without the ability to hand-key credit card numbers when the card swipe fails to read the magnetic stripe? Hand-keyed cards will almost always result in credit card numbers being introduced back into the memory of the POS terminal. If the card swipe peripheral device allows customers to hand-key credit card numbers, just imagine the potential for fraud.

Many “hardware encryption” advocates fail to recognize how firmware equals software. Does your dedicated “hardware encryption” device have firmware or is the encryption logic printed in silicon? Is there a mechanism to remotely push updated firmware or does the firmware have any remotely exploitable bugs? How are the keys managed? There probably is some sort of memory in your favorite device, but the good news is it may not be possible to remotely scrape. Additionally, it may have some physical tamper resistance built into it, which will certainly inhibit a wide-scale memory scraping attack.

Encrypted card swipe devices are a good strategic direction to take, however, not all retailers have the funds or capability to invest in that technology. Or perhaps the investment will take years to completely roll out. What tactical changes can be made today to minimize exposure?

SecureStrings

Many high-level languages have constructs for “secure strings.” This typically means that there will be a single copy of the value on the heap, as opposed to littered all over the heap, like in the example above. This also can mean the physical values in RAM are encrypted, but any good penetration tester will tell you that the implementation is only as good as its key management. The problem with most SecureStrings implementations is that it limits practicality and compatibility. If your in-house developed applications rely on APIs that do not support passing credit cards as SecureStrings, then your code will at some point need to cast the SecureString into its memory-scrapeable cousin, the plain old regular string, which will resume the littering of credit cards on the heap again. This also happens when you pull data from a database persistence layer. If a DB API exposes a method to retrieve a SecureString from a query result, the API likely will retrieve the raw query results from the DB as a traditional string first. Thus, the sensitive data will exist in RAM at least momentarily.

E-Commerce

Memory scraping certainly isn’t limited to traditional brick-and-mortar retail. If an e-commerce web server can be exploited, and its memory dumped, then an attacker will likely find sensitive data there as well. With web applications, SecureStrings won’t be usable until after it’s too late. When the web server receives a POST request containing a credit card transaction — even if your business logic casts the values to a SecureString — all of the request parameters land on the heap as a regular string at least once prior to the cast. Add in caching layers to improve the speediness of round-trip data requests, and all kinds of sensitive goodies are likely to be found in a memory dump. Implementing end-to-end encryption to keep the plaintext credit card out of the web application’s memory heap would require hardware devices to be deployed to each customer, which probably won’t ever make financial (or security) sense.

Other Operating Systems

The memory scraping example above is for Windows, but in reality any platform is potentially vulnerable, since most have API mechanisms to read memory of processes at the same or lower privilege level. If there are no readily available APIs to dump a process’s memory (e.g. /dev/mem on *nix platforms), then an attacker could even attempt to freeze the RAM and use a cold boot attack on a POS machine or exploit Direct Memory Access (DMA) using a firewire device (of course both of those attacks require physical access). When a group of Princeton grad students performed their cold boot attack on whole disk encryption, they were essentially performing the exact same attack — memory scraping — looking for encryption keys, which is arguably much harder than locating a simple 16-digit number in an array of bytes.[Corollary: Beware the “support guy” with the canned air, USB drives and fake work order to fix a POS back office server on Black Friday.]

In Summary

Preventing memory scraping is hard and most likely affects your POS or e-commerce system. From a security economics perspective, as the cost to attack the non-volatile storage and transmission of sensitive data increases, the cost to attack sensitive data in volatile memory decreases. It should not be a surprise that state-of-the-art malware uses memory scraping.