Trolling Memory for Credit Cards in POS / PCI Environments

Published: 2014-08-26
Last Updated: 2014-08-26 01:06:24 UTC
by Rob VandenBrink (Version: 1)
4 comment(s)

In a recent penetration test, I was able to parlay a network oversight into access to a point of sale terminal.  Given the discussions these days, the next step for me was an obvious one - memory analysis.

My first step was to drive to the store I had compromised and purchase an item.

I'm not a memory analysis guru, but the memory capture and analysis was surprisingly easy.  First, dump memory:
dumpit
Yup, it's that simple, I had the dumpit executable locally by that point (more info here https://isc.sans.edu/diary/Acquiring+Memory+Images+with+Dumpit/17216)
or, if you don't have keyboard access (dumpit requires a physical "enter" key, I/O redirection won't work for this):
win32dd /f memdump.img
(from the SANS Forensics Cheat Sheet at https://blogs.sans.org/computer-forensics/files/2012/04/Memory-Forensics-Cheat-Sheet-v1_2.pdf )

Next, I'll dig for my credit card number specifically:

strings memdump.img | grep [mycardnumbergoeshere] | wc -l
     171

Yup, that's 171 occurences in memory, unencrypted.  So far, we're still PCI complaint - PCI 2.0 doesn't mention cardholder data in memory, and 3.0 only mentions it in passing.  The PCI standard mainly cares about data at rest - which to most auditors means "on disk or in database", or data in transit - which means on the wire, capturable by tcpdump or wireshark.  Anything in memory, no matter how much of a target in today's malware landscape, is not an impact on PCI compliance.

The search above was done in windows, using strings from SysInternals - by default this detects strings in both ASCII and Unicode.  If I repeat this in linux (which by default is ASCII only), the results change:
strings memdump.img | grep [mycardnumbergoeshere] | wc -l
     32

To get the rest of the occurences, I also need to search for the Unicode representations,  which "strings" calls out as "little-endian" numbers:
strings -el memdump.img | grep [mycardnumbergoeshere] | wc -l
     139

Which gives me the same total of 171.

Back over to windows, let's dig a little deeper - how about my CC number and my name tied together?
strings memdump.img | grep [myccnumbergoeshere] | grep -i vandenbrink | wc -l
     1

or my CC number plus my PIN  (we're CHIP+PIN in Canada)
strings memdump.img | grep [mycardnumbergoeshere] | grep [myPINnumber]
     12

Why exactly the POS needs my PIN is beyond me!

Next, let's search this image for a number of *other* credit cards - rather than dig by number, I'll search for issuer name so there's no mistake.  These searches are all using the Sysinternals "strings" since the defaults for that command lend itself better to our search:

CAPITAL ONE       85
VISA             565
MASTERCARD      1335
AMERICAN EXPRESS  20

and for kicks, I also searched for debit card prefixes (I only search for a couple with longer IIN numbers):
Bank of Montreal   500766     245
TD CAnada Trust    589297    165

Looking for my number + my CC issuer in the same line gives me:
strings memdump.img | grep [myccnumbergoeshere] | grep [MASTERCARD] | wc -l
gives me a result of "5"

So, assuming that this holds true for others (it might not, even though the patterns are all divisible by 5), this POS terminal has hundreds, but more likely thousands of valid numbers in memory, along with names, PIN numbers and other informaiton

Finally, looking for a full magstripe in memory:

The search for a full stripe:
grep -aoE "(((%?[Bb]?)[0-9]{13,19}\^[A-Za-z\s]{0,26}\/[A-Za-z\s]{0,26}\^(1[2-9]|2[0-9])(0[1-9]|1[0-2])[0-9\s]{3,50}\?)[;\s]{1,3}([0-9]{13,19}=(1[2-9]|2[0-9])(0[1-9]|1[0-2])[0-9]{3,50}\?))" memdump.img  | wc -l
    0

where:

    -a = Processes a binary file as text
    -o = Shows only the matched text
    -E = Treats the pattern as an extended regular expression

or using this regex to find Track strings only:

((%?[Bb]?)[0-9]{13,19}\^[A-Za-z\s]{0,26}\/[A-Za-z\s]{0,26}\^(1[2-9]|2[0-9])(0[1-9]|1[0-2])[0-9\s]{3,50}\?)
gives us 0 results.

or this regex to find Track 2 strings only:

([0-9]{13,19}=(1[2-9]|2[0-9])(0[1-9]|1[0-2])[0-9]{3,50}\?)  
Gives us 162  (I'm not sure how much I trust this number)

Anyway, what this tells me is that this store isn't seeing very many folks swipe their cards, it's all CHIP+PIN (which you'd expect)

(Thanks to the folks at bromium for the original regular expressions and breakdown: http://labs.bromium.com/2014/01/13/understanding-malware-targeting-point-of-sale-systems/)

Getting system uptime (from the system itself) wraps up this simple analysis - the point of this being "how long does it take to collect this much info?"

net statistics server | find "since""
shows us that we had been up for just under 4 days.

Other ways to find uptime?
from the CLI:
systeminfo " find "Boot Time"
or, in powershell:
PS C:\> Get-WmiObject win32_operatingsystem | select csname, @{LABEL='LastBootUpTime';EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}
or, in wmic:
wmic get os last bootuptime
or, if you have sysinternals available, you can just run "uptime"


What does this mean for folks concerned with PCI compliance?
Today, not so much.  Lots of environments are still operating under PCI 2.0.  PCI 3.0 simply calls for education on the topic of good coding practices to combat memory scraping.  Requirement 6.5 phrases this as "Train developers in secure coding techniques, including how to avoid common coding vulnerabilities, and understanding how sensitive data is handled in memory.  Develop applications based on secure coding guidelines."

Personally (and this is just my opinion), I would expect/hope that the next version of PCI will call out encryption of card and personal information in memory specifically as a requirement.  If things play out that way, What this will mean to the industry is that either:
a/ folks will need to move to card readers that encrypt before the information is on the POS terminal
or
b/ if they are using this info to collect sales / demographic information, they might instead tokenize the CC data for the database, and scrub it from memory immediately after.  All  I can say to that approach is "good luck".  Memory management is usually abstracted from the programming language, so I'm not sure how successful you'd be in trying to scrub artifacts of this type from memory.

===============
Rob VandenBrink, Metafore

Keywords:
4 comment(s)

Comments

Thanks for posting this!
The more I read the more it seems the PCI council is
A)Woefully behind the times and B) Hopelessly conflicted.

"Anything in memory, no matter how much of a target in today's malware landscape, is not an impact on PCI compliance."

This sentence explains how a site can be PCI compliant and yet remain totally vulnerable.


"What does this mean for folks concerned with PCI compliance? Today, not so much. Lots of environments are still operating under PCI 2.0. PCI 3.0 simply calls for education on the topic of good coding practices to combat memory scraping."

And that paragraph drives a nail into the hopes of being secure unless one deploys encrypting card readers. Of course you can't get PCI certified with just any encrypting reader it must also be PCI-certified and the only vendor in the US to be certified makes their product out of unobtanium.? They literally don't have any.
You are simply wrong about your PCI-DSS related statements Rob, please correct your original post as it is dangerously misleading the readers.

PCI-DSS standard states that it "applies wherever account data is stored, processed or transmitted."
To me, as a QSA, this includes memory and does not end at data at rest as you stated.

Based on my experience, problems with the PCI-DSS often come out of non-compliance (PA-DSS or PCI PTS/POI are involved as well) and sometimes this is a direct consequence of the lack of skill/knowledge from the QSA or a non-QSA making the wrong interpretation. The standard tries to clarifies it better along the versions to avoid such misinterpretations. In version 3.0, some explicit clarifications about memory have been made in requirements 6.3, 6.5.

Kind regards,
Nicolas Villatte.
I think we'll need to agree to disagree on this one.

Memory is not mentioned in PCI 2.0 at all. In PCI 3.0, memory is specifically excluded in some areas, and where it is mentioned it's in the context of encouraging developers to be educated in protecting memory.

Because of this lack of guidance, most QSA's take "data at rest" to mean "on disk, or in a database" and "data in transit" to mean "data on the wire or wireless network".

Every POS application that I've seen that has access to cardholder data stores it in memory in the clear - masking and encryption is only done when written to disk or network. Since no-one is forcing the vendors or the developers to protect memory, the outcome is predictable - no-one protects memory.

Given the leading statements in PCI 3.0, along with the prevalence and success of memory scraping malware in the last few years, I'm hopeful that the PCI council will release an interim document on this, or possibly include stronger guidance in PCI 4.0.

Diary Archives