Having investigated cardholder data security breaches for a few years now, I have noticed changes in attacker behavior when choosing entities to target. Over the past 3 years trends in attack vectors have been transformed as the hacker community matured and set their sights on larger organizations to prey on. The migration from attacking small merchants to large-scale organizations brings with it a whole host of changes to the forensic community, particularly the differences in technologies used in the environments that are now being targeted. In the past, it was simple enough to investigate a small ecommerce merchant that had been compromised via SQL injection, now with larger service providers and banks being the targets of compromises the focus if the investigation shifts from mainstream cardholder data transmission protocols like TCP/IP to the less common types such as the standard for Financial Transaction Card Messages, ISO8583.
This legibility usually fools the investigator into thinking that card data would be clearly visible in this format. This is not the case; a lot more dissection needs to take place before the data is fully extracted. ISO8583 traffic consists of 3 major parts as follows:
Figure 2 – ISO8583 Message Elements
There are already several whitepapers that discuss all the data fields available in an ISO8583 message block; however, the primary focus for this and most investigations is to strip out the card data from the message block captured on the wire. The following are the main points to note when producing POC code to strip out the cards from the block:
- The MTI (Message Type Indicator) is the first field of every ISO8583 message block and contains metadata such as message version, class and origin.
- Every ISO8385 message block has at least 1, 64-bit bitmap that has to be taken into account. Some setups make use of 2 or more bitmaps depending on the inclusion of other proprietary and reserved fields. The information in the bitmaps will indicate which data elements are present in the message block being analyzed.
- Every other field that is not directly lined to the cardholder’s Primary Account Number (PAN) can be neglected for the purpose of the production of the POC code; nevertheless the code can be customized to pull out other fields as necessary.
As shown in figure 1, each message block started with an EBCDIC encoded “ISO8583-1987” clause. This clause is the part of the MTI that denotes the ISO8583 version in use; in this case the 1987 version of the standard was used. An intuitive approach would be to imagine all the data succeeding this header clause, but preceding the next header to be part of the same message block.
From a very high level, the part of the MTI that immediately follows the version is the message class, this tells us the exact purpose of the massage. In our case ‘0x0200’ denotes a financial message originating from an acquirer.
Probably the most important part of the message block is the primary bitmap. This immediately follows the “Message Class” section of the MTI. The first step would be to analyze the bitmap to determine where the credit cards sits in relation to the beginning of the message block if at all any exist. For this exercise, every other piece of data is considered irrelevant. As each bitmap is 64-bits in length, extraction of the 64-bits immediately following the message class would give us the following hexadecimal value from figure 1:
Figure 3 – Primary Bitmap from Figure 1
Decoding this value would give us the following binary equivalent:
Figure 4 – Binary Equivalent of Primary Bitmap
Making sense of this information is a relatively simple process from here on. ISO8583 defines at least 128 data elements that can possibly exist in each message block. Each binary digit from all the present bitmaps will denote the presence of a field in the spaces remaining for the data elements. The table below shows an example of some of the data elements that have been defined by the ISO8583 standard. Only the first 7 data elements have been included below.
|Data Element||Data Type||Description|
|1||Binary||Bitmap of up to 192 bits|
|2||Numeric||Primary Account Number (PAN) of up to 19 characters|
|3||Numeric||6 digit Processing Code|
|4||Numeric||12 Digit Transaction Amount|
|5||Numeric||12 Digit Settlement Amount|
|6||Numeric||12 Digit Cardholder Billing Amount|
|7||Numeric||10 Digit value specifying transmission Time and Date|
Figure 5 – Data Elements Description Table, First 7 Values
The list of data elements goes all the way up to at least 128. Each element’s data type could be binary, numeric or even alphanumeric depending on the data transmitted in the filed.
Now, consolidating information from this data elements table with the results obtained from decoding the mandatory primary bitmap, we can mow make sense of what fields to expect and how long they will be. Every positive bit in the decoded bitmap denotes the presence of the corresponding field, whilst the naughts represent the absence of a field, more importantly though, all readings are taken from the left toward the right. Therefore, taking into account the first 4 bytes of the decoded binary output from the primary bitmap as an example we can tell the following:
01110010 Fields 2,5,6, and 7 are present
00111110 Fields 10,11,12,13,14 are present
11100100 Fields 19,22,23 and 24 are
10000001 Fields 25 and 32 are present
Referring back to the table, we can draw the following conclusions:
- A secondary bitmap is not present
- The Primary Account Number (PAN) is in the message block
- The Settlement and Billing amounts are present
- Dates and Times of each transaction can be harvested from the message block
Now that we know what data is present, we can produce POC code that will allows us to strip out PANs from each message as follows.
Figure 6 – POC Code to extract PANs from the ISO8583 Message block
It is apparent from the code that for the purposes of this exercise, everything that is not the PAN is read and disregarded. The script can be altered to pull out any field as required as the presence of each field and its length is clearly shown in the bitmap. A lot more can be done with this code to produce a much more robust tool that dynamically choses the field to extract on demand… however, at this point, deciphering and extracting credit cards sounds like a good starting point to me!