this is the archive page

Equifax: A Case Study in Vulnerability Management

By now you’ve surely heard about the Equifax breach. (Of course I have, Justin, and don’t call me Shirley.)

I was actually quite surprised when the details of this breach were announced; specifically, that the initial point of entry into the Equifax network was not phishing. Instead, the attackers found and exploited a vulnerability in a public-facing web application framework. This allowed them to take control of the server on which this software was running, and use it as an entry point to the internal network and, eventually, to 143 million PII records.

This certainly calls to mind the old adage “the attackers only have to be lucky once – you have to be lucky every time.”

Equifax used Apache Struts – the web application framework in question – as a part of its online disputes application. US-CERT, a division of the federal government charged with helping Americans protect their data from security threats, notified Equifax about a serious vulnerability in Struts. The Equifax information security team passed this notification to the IT operations teams responsible for patching, as described in the Congressional testimony from Equifax CEO Richard Smith:

“On March 9, Equifax disseminated the U.S. CERT notification internally by e-mail requesting that applicable personnel responsible for an Apache Struts installation upgrade their software. Consistent with Equifax’s patching policy, the Equifax security department required that patching occur within a 48 hour time period. We now know that the vulnerable version of Apache Struts within Equifax was not identified or patched in response to the internal March 9 notification to information technology personnel.”

In addition, he notes:

“On March 15, Equifax’s information security department also ran scans that should have identified any systems that were vulnerable to the Apache Struts issue identified by U.S. CERT. Unfortunately, however, the scans did not identify the Apache Struts vulnerability.”

So here we have two breakdowns in the system: a failure to patch, and a failure to identify the application as vulnerable.

It’s a great reminder of why we consider the discipline of vulnerability management to involve much more than simple vulnerability scanning or patching. We see it as a checks-and-balances, in a way, to the IT operations teams that manage the computing environment. A complete practice would include:

  • An authorized software list, defining which applications are permitted for use in the organization’s computing environment
  • An effort to remove unauthorized software not present on this list from the environment on a regular basis
  • Notifications from vendors responsible for software on this list concerning new vulnerabilities
  • Self-guided research from internal security staff to find undiscovered or undocumented vulnerabilities
  • Ongoing vulnerability scans to find missing patches, configuration flaws, and design weaknesses  in all network nodes – servers, workstations, network devices, mobile devices, peripherals (such as cameras, networked printers, card readers, etc.)
  • Manual identification of serious vulnerabilities that may not be picked up by vulnerability scans, researchers, penetration testers, or a red team
  • Regular reports of vulnerabilities and remediation guidance to those responsible for system administration

This kind of formal practice is not trivial to build, but it can be done over time in a series of phases. And there’s still no guarantee you won’t miss something, as Equifax did. And even if your hygiene is perfect, the attackers could still try to phish you.

It’s not hopeless – our ultimate goal is to make attacking our organization so taxing and costly for the attacker that they give up and move on to another target; and if they are successful, identifying the breach and responding effectively. Equifax may not have been lucky this time; here’s hoping we can learn from their mistakes.


Related Articles:

BlackPOS or Something New – Tracking Point of Sale Malware

Three steps to enhancing security solutions

BlackPOS or Something New – Tracking Point of Sale Malware

Tracking Point of Sale malware and determining if the malware from the Home Depot Cyber Attack was different than what was used on Target

Using Intelligent Analysis and Adaptive Defense, all of us at CBTS Advanced Cyber Security want to learn from past attacks in order to better defend our customers from future attacks. Many times this involves finding new and novel ways to track malware, even point of sale malware. To this end, we became very interested when TrendMicro reported on a new variant of BlackPOS, which we will call MEMLOG.A for the sake of this post. In the blog post they are correlating this to the malware used to target Home Depot in the latest hack.

While it’s sensational to say that the same malware was used to target both Home Depot and Target, this is not looking like the case. There are already some entries coming out from other reverse engineers on this subject and this is not looking like BlackPOS at all.

Tracking Point of Sale Malware

In the blog post, TrendMicro alludes to the custom algorithm being used inside MEMLOG.A to validate and process CC information. “Based on our analysis, this PoS malware uses a new custom search routine to check the RAM for Track data. These custom search routines have replaced the regex search in newer PoS malware.” No other information is provided. On seeing this, we thought that perhaps these algorithms could be used as a way to track and identify Point of Sale malware. The MEMLOG.A sample that TrendMicro wrote up would be a good experiment to find out how similar these algorithms are across all Point of Sale malware.

Point of Sale malware often uses the same technique to find credit card numbers on the victim machine. The malware will scrape memory and then search for valid numbers. Regex is often used to find the numbers and then they are passed to a validation algorithm, in almost all cases this is Luhn’s algorithm. Normally, search for an implementation of Luhn’s algorithm on a Point of Sale machine will identify malware. In this case, when a custom algorithm is used, this is somewhat rare case, and interesting to anyone chasing POS malware. That said, by implementing a new and unique algorithm, the malware actually becomes easier to detect because nothing else uses that algorithm.

Detecting Point of Sale Malware

In the case of the MEMLOG.A malware that TrendMicro wrote up, the algorithms can be easily abstracted into yara rules to flag anytime the suspect algorithms exist inside a set of code. Even better, these rules will flag on other samples using the same algorithm. By implementing these rules, defenders can detect not just this version of the malware, but any version that uses this algorithm to find Track data in RAM. This will essentially force the attacker to rewrite their code or face detection.

rule Production_POS_CC_Algorithm
author = “Nick Hoffman – CBTS – ACS”
description = “Finds CC validation routines”
//00401224 |> /48 /DEC EAX
//00401225 |. |0FBE0C06 |MOVSX ECX,BYTE PTR DS:[ESI+EAX]
//00401229 |. |83E9 30 |SUB ECX,30
//0040122C |. |85FF |TEST EDI,EDI
//0040122E |. |75 04 |JNZ SHORT b579c886.00401234
//00401230 |. |8B4C8D D4 |MOV ECX,DWORD PTR SS:[EBP+ECX*4-2C]
//00401234 |> |03D9 |ADD EBX,ECX
//00401236 |. |33C9 |XOR ECX,ECX
//00401238 |. |85FF |TEST EDI,EDI
//0040123A |. |0F94C1 |SETE CL
//0040123D |. |8BF9 |MOV EDI,ECX
//0040123F |> |85C0 TEST EAX,EAX
//00401241 |.^\75 E1 \JNZ SHORT b579c886.00401224
$a = {480FBE0C0683E93085FF75 048B4C8DD403D933C985FF0F94C18BF985C075 E1 }
//004011DC |. 895D D4 MOV [LOCAL.11],EBX
//004011DF |. C745 D8 02000000 MOV [LOCAL.10],2
//004011E6 |. C745 DC 04000000 MOV [LOCAL.9],4
//004011ED |. C745 E0 06000000 MOV [LOCAL.8],6
//004011F4 |. C745 E4 08000000 MOV [LOCAL.7],8
//004011FB |. 8945 E8 MOV [LOCAL.6],EAX
//004011FE |. C745 EC 03000000 MOV [LOCAL.5],3
//00401205 |. C745 F0 05000000 MOV [LOCAL.4],5
//0040120C |. C745 F4 07000000 MOV [LOCAL.3],7
//00401213 |. C745 F8 09000000 MOV [LOCAL.2],9
$loadevenodd = {895D ?? C745 ?? 02000000 C745 ?? 04000000 C745 ?? 06000000 C745 ?? 08000000 8945 ?? C745 ?? 03000000 C745 ?? 05000000 C745 ?? 07000000 C745 ?? 09000000}
//.text:0040136E ; 22: if ( v4 )
//.text:0040136E 83 7D E0 00 cmp [ebp+var_20],
//.text:00401372 74 1F jz short loc_401393
//.text:00401374 ; 24: v6 *= 2;
//.text:00401374 8B 45 F8 mov eax, [ebp+var_8]
//.text:00401377 D1 E0 shl eax, 1
//.text:00401379 89 45 F8 mov [ebp+var_8], eax
//.text:0040137C ; 25: if ( (signed int)v6 > 9 )
//.text:0040137C 83 7D F8 09 cmp [ebp+var_8], 9
//.text:00401380 7E 11 jle short loc_401393
//.text:00401382 ; 26: v6 = (signed int)v6 % 10+ 1;
//.text:00401382 8B 45 F8 mov eax, [ebp+var_8]
//.text:00401385 99 cdq
//.text:00401386 B9 0A 00 00 00 mov ecx, 0Ah
//.text:0040138B F7 F9 idiv ecx
//.text:0040138D 83 C2 01 add edx, 1
//.text:00401390 89 55 F8 mov [ebp+var_8], edx
//.text:00401393 ; 28: v4 = v4 == 0;
//.text:00401393 loc_401393: CODE XREF: //.text:00401393 sub_4012D0+B0j
//.text:00401393 33 C0 xor eax, eax
//.text:00401395 83 7D E0 00 cmp [ebp+var_20], 0
//.text:00401399 0F 94 C0 setz al
//.text:0040139C 89 45 E0 mov [ebp+var_20], eax
//.text:0040139F ; 29: v3 += v6;
//.text:0040139F 8B 45 D4 mov eax, [ebp+var_2C]
//.text:004013A2 03 45 F8 add eax, [ebp+var_8]
//.text:004013A5 89 45 D4 mov [ebp+var_2C], eax
//.text:004013A8 EB 8C jmp short loc_401336
//.text:004013AA ; 31: result = v3 % 10 == 0;
//.text:004013AA loc_4013AA: ; //.text:004013AA 8B 45 D4 mov eax, [ebp+var_2C]
//.text:004013AD 99 cdq
//.text:004013AE B9 0A 00 00 00 mov ecx, 10
//.text:004013B3 F7 F9 idiv ecx
//.text:004013B5 F7 DA neg edx
//.text:004013B7 1B D2 sbb edx, edx
//.text:004013B9 42 inc edx
//.text:004013BA 8B C2 mov eax, edx
//.text:004013BC ; 42: return result;
$blackpos = {83 7D E0 00 74 1F 8B 45 F8 D1 E0 89 45 F8 83 7D F8 09 7E 11 8B 45 F8 99 B9 0A 00 00 00 F7 F9 83 C2 01 89 55 F8 33 C0 83 7D E0 00 0F 94 C0 89 45 E0 8B 45 D4 03 45 F8 89 45 D4 EB 8C 8B 45 D4 99 B9 0A 00 00 00 F7 F9 F7 DA 1B D2 42 8B C2}
any of them

Comparing the Algorithms

Now that we know how to detect this new malware, let’s look at how it differs from past Point of Sale malware samples. In many cases Point of Sale malware has used a variant of Luhn’s algorithm. Understanding the different ways that this algorithm is implemented can help us differentiate between families of malware. Taking a look at a classic Luhn’s would yield the following code (in C++)

int confirm( const char *id)
bool is_odd_dgt = true;
int s = 0;
const char *cp;

for(cp=id; *cp; cp++);
while(cp > id) {
int k = toInt(*cp);
if (is_odd_dgt) {
s += k;
else {
s += (k!=9)? (2*k)%9 : 9;
is_odd_dgt = !is_odd_dgt;
return 0 == s%10;

Now let’s compare this to the MEMLOG.A malware. For MEMLOG.A the following function stands out.

BlackPOS POS Malware

In classic Luhn’s implementation logic is used to keep track of odd and even numbers. In the MEMLOG.A implementation a lookup table is used to track odd and even numbers. This is a stylistic difference that is significant in determining the origin of each piece of malware.

Translating the MEMLOG.A implementation into pseudo-code will show the following

v1 = 0;
v6 = 0;
v7 = 2;
v8 = 4;
v9 = 6;
v10 = 8;
v11 = 1;
v12 = 3;
v13 = 5;
v14 = 7;
v15 = 9;
v2 = 1;
v3 = strlen(a1);
while ( v3 ) {
v4 = a1[v3] – 48;
if ( !v2 )
v4 = *(&v6; + v4);
v1 += v4;
v2 = v2 == 0;
return v1 % 10 == 0;

Comparing the MEMLOG.A pseudo-code to pseudo-code from the BlackPOS samples found in Target, shows us that these are two very different implementations.

int __cdecl sub_4012D0(char *a1)
int result; // eax@2
char v2; // [sp+Ch] [bp-F0h]@1
int v3; // [sp+D0h] [bp-2Ch]@6
int v4; // [sp+DCh] [bp-20h]@6
size_t i; // [sp+E8h] [bp-14h]@6
size_t v6; // [sp+F4h] [bp-8h]@3
memset(&v2;, 0xCCu, 0xF0u);
if ( a1 )
v6 = strlen(a1);
if ( (signed int)v6 >= 13 && (signed int)v6 <= 19 )
v4 = 0;
v3 = 0;
for ( i = v6 – 1; (signed int)i > -1; –i )
if ( !isdigit(a1[i]) )
return 0;
v6 = a1[i] – 48;
if ( v4 )
v6 *= 2;
if ( (signed int)v6 > 9 )
v6 = (signed int)v6 % 10 + 1;
v4 = v4 == 0;
v3 += v6;
result = v3 % 10 == 0;
result = 0;
result = 0;
return result;

The BlackPOS sample would align more with a close (classic) implementation of Luhn’s. Our MEMLOG.A sample is using the idea of Luhn’s with a different implementation.

While this is just one small piece of the functionality of these two families of malware, it helps highlight the differences both stylistically and functionally.

Chasing these algorithms will help in tracking the different evolutions of this malware (and algorithm) over time. By pulling indicators of longevity like this algorithm from known malware, we can push that defense out to our clients. Now they’re protected against what hit Home Depot and any other variant that follows.

Related Articles:

Equifax: A Case Study in Vulnerability Management

Three steps to enhancing security solutions