Blog

Get the most innovative insights

Sort By

iClass Is Not Enough

Hacking iClass for Fun, Door-Entry and a Free Lunch.  iClass has been broken in the public domain since approximately 2010 when Meriac published his findings at the 27th CCC in Berlin with the Heart of Darkness White-paper.  But why does there appear to be limited support for hacking these cards within the community? The cards have been in the industry since 2001, boasting stronger security then the original Mifare.  Since the Heart of Darkness publication HID Global appear to have pulled all their public documentation, and now you have to sign NDA’s go get the documentation needed to learn more about these cards.  Also the HID RW300 Rev A Reader Meric exploited is now in short supply.  There are a few other readers on eBay etc; but they are typically Rev B or C, which use a different micro-controller that isn’t vulnerable to the same attack Meriac used to extract HID’s Master Authentication & Decryption Keys – which are still in use today!

iclass read & card

After patiently stalking eBay and other tech recycling companies; I was lucky enough to obtain a single HID RW300 Rev A, this post will walk through the exploit used to obtain the keys, and follow Meriac’s initial research and exploits.

Breaking iClass has made me more determined in recent weeks, due to my increased involvement with clients using standard iClass security…

An Unsuccessful Quick Hack

With only one Reader I initially tried following the iclass-dump post from Foundstone.  I’m used to bit-banging with Arduino and FTDI cables so though this would be a quick exploit.  After weeks of dumping 0’s I was beginning to think that either my reader was broken or that I was doing something wrong?  I swapped Operating Systems, FTDI cables, even coded my own bit-banging program before giving-up.  At this point I new nothing was wrong with my reader, that the relationship (or speed of communication) between the RW300 and my computers was off.  The ICSP protocol on the micro-controller (PIC18F452) is very particular about the speed responses, a fraction of a second off, and you fail to talk to the device.

Hacking – the Right Way

With this method abandoned, I turned back to the Proxmark3 forums, where I was advised to follow the Heart of Darkness whitepaper; but I only had one reader!

In the end I managed to borrow a reader from a friend! which allowed me to successfully dump the RW300’s memory (further down the page).

I purchased a Pickit2 Starter Kit from eBay, and started to play around with their demo’s to familiarise myself with the PIC chipset and the Pickit2 device.  I ordered some Male-2-Male Jumper wire from Adafruit. To easily swap the Pin 1 (MCLR) and Pin 3 (VPP), and connected the Pickit2 to the RW300 Rev A (notice in the picture below, that the black and grey cables on one end are the other way around), I did not bother with any extra voltage like the iclass-dump posting; I Just relied on the voltage/ampage coming natively out of my USB port and and Pickit2 programmer.

Pickit2 Cable
Flashing RW300 RevA

Trying to read the EEPROM resulted in:

Picket2 connected to Pic18F - no access

I turned back to ‘Heart of Darkness’ where they used an FTDI cable and compiled the pic18-icsp programs (available in http://www.openpcd.org/git-view/iclass-security/) to dump the firmware. So I broke out my FTDI cable, once again hooked it up then successfully dumped the firmware (blocks 0-3) on one device, and the boot block on another. Then I reused the device with the wiped firmware and the intact boot loader; it now has a lot of free space since I wiped the firmware, I could now reuse this device again ( second time) to dump the EEPROM.

With all 3x dumps I could stitch the completed firmware back together (just like humpty-dumpty) and then use bin2hex (http://www.bialix.com/intelhex/) to convert the binary dump to an intel hex file – ready for flashing!

With the assembled dump & .hex file I next opened up the Pickit2 Programmer software.  Selected my chipset (PIC18F452), clicked the “Auto Import Hex + Write Device” button, and selected my manufactured .hex file.  And successfully flashed the Reader!  Now to swipe a card under the reader and read the EEPROM.

The Reader beeped , and the LEDs flashed indicating everything is working correctly…

Picket2 connected to Pic18F - no access

…except the EEPROM dump failed!

I forgot that I had left on both ‘Code Protect’ and ‘Data Protect’ from the Pickit2’s Tools Menu.  Doh! So I boxed up that Reader and posted it back to my friend (it being in its original condition).  I had the binary .hex file so re-flashed ‘my’ reader (this time turning off code protection and data protection).  Powered up the reader, read a card to ensure it was working (beeps and LEDs flashing – bingo).  Then proceeded to dump the EEPROM.  The information in the ‘Heart of Darkness’ paper was right.  I now had the MASTER KEYS I’d been trying so hard to retrieve.

pickit2_pic18f_eeprom_access

Note: No keys are shown in the screenshot above!

Hack Complete – Reading iClass Cards

I then turned to Meriac’s CopyClass program (from http://www.openpcd.org/git-view/iclass-security/), entered the keys compiled the program to read my iClass card with HIDs Omnikey 5321 Reader.

I then decided to add to Meriac’s Code to help me to quickly dissect iClass tags and display the meaning of various bytes.

My slightly improved version looks like:

iClass Captured Card

It should auto-detect between 2K and 16K cards, you can use the ‘choose book’ to read different pages/books stored on the card.  And hopefully all  sectors with data should automatically decrypt (provided you have the right key!).  The code is available within PenturaLabs’ github repository:  https://github.com/PenturaLabs/iClassReader

Thanks

At this point I would like to thank Roel Verdult, Flavio D. Garcia, Milosch Meriac and Carl(http://www.proxclone.com); for their patience, quick respones to questions, guidance and support.  Also thanks to my mate who wishes to remain anonymous for supplying the second RW300 RevA Reader.

Hacking iClass for Fun, Door-Entry and a Free Lunch.  iClass has been broken in the public domain since approximately 2010 when Meriac published his findings at the 27th CCC in Berlin with the Heart of Darkness White-paper.  But why does there appear to be limited support for hacking these cards within the community? The cards have been in the industry since 2001, boasting stronger security then the original Mifare.  Since the Heart of Darkness publication HID Global appear to have pulled all their public documentation, and now you have to sign NDA’s go get the documentation needed to learn more about these cards.  Also the HID RW300 Rev A Reader Meric exploited is now in short supply.  There are a few other readers on eBay etc; but they are typically Rev B or C, which use a different micro-controller that isn’t vulnerable to the same attack Meriac used to extract HID’s Master Authentication & Decryption Keys – which are still in use today!

iclass read & card

After patiently stalking eBay and other tech recycling companies; I was lucky enough to obtain a single HID RW300 Rev A, this post will walk through the exploit used to obtain the keys, and follow Meriac’s initial research and exploits.

Breaking iClass has made me more determined in recent weeks, due to my increased involvement with clients using standard iClass security…

An Unsuccessful Quick Hack

With only one Reader I initially tried following the iclass-dump post from Foundstone.  I’m used to bit-banging with Arduino and FTDI cables so though this would be a quick exploit.  After weeks of dumping 0’s I was beginning to think that either my reader was broken or that I was doing something wrong?  I swapped Operating Systems, FTDI cables, even coded my own bit-banging program before giving-up.  At this point I new nothing was wrong with my reader, that the relationship (or speed of communication) between the RW300 and my computers was off.  The ICSP protocol on the micro-controller (PIC18F452) is very particular about the speed responses, a fraction of a second off, and you fail to talk to the device.

Hacking – the Right Way

With this method abandoned, I turned back to the Proxmark3 forums, where I was advised to follow the Heart of Darkness whitepaper; but I only had one reader!

In the end I managed to borrow a reader from a friend! which allowed me to successfully dump the RW300’s memory (further down the page).

I purchased a Pickit2 Starter Kit from eBay, and started to play around with their demo’s to familiarise myself with the PIC chipset and the Pickit2 device.  I ordered some Male-2-Male Jumper wire from Adafruit. To easily swap the Pin 1 (MCLR) and Pin 3 (VPP), and connected the Pickit2 to the RW300 Rev A (notice in the picture below, that the black and grey cables on one end are the other way around), I did not bother with any extra voltage like the iclass-dump posting; I Just relied on the voltage/ampage coming natively out of my USB port and and Pickit2 programmer.

Pickit2 Cable
Flashing RW300 RevA

Trying to read the EEPROM resulted in:

Picket2 connected to Pic18F - no access

I turned back to ‘Heart of Darkness’ where they used an FTDI cable and compiled the pic18-icsp programs (available in http://www.openpcd.org/git-view/iclass-security/) to dump the firmware. So I broke out my FTDI cable, once again hooked it up then successfully dumped the firmware (blocks 0-3) on one device, and the boot block on another. Then I reused the device with the wiped firmware and the intact boot loader; it now has a lot of free space since I wiped the firmware, I could now reuse this device again ( second time) to dump the EEPROM.

With all 3x dumps I could stitch the completed firmware back together (just like humpty-dumpty) and then use bin2hex (http://www.bialix.com/intelhex/) to convert the binary dump to an intel hex file – ready for flashing!

With the assembled dump & .hex file I next opened up the Pickit2 Programmer software.  Selected my chipset (PIC18F452), clicked the “Auto Import Hex + Write Device” button, and selected my manufactured .hex file.  And successfully flashed the Reader!  Now to swipe a card under the reader and read the EEPROM.

The Reader beeped , and the LEDs flashed indicating everything is working correctly…

Picket2 connected to Pic18F - no access

…except the EEPROM dump failed!

I forgot that I had left on both ‘Code Protect’ and ‘Data Protect’ from the Pickit2’s Tools Menu.  Doh! So I boxed up that Reader and posted it back to my friend (it being in its original condition).  I had the binary .hex file so re-flashed ‘my’ reader (this time turning off code protection and data protection).  Powered up the reader, read a card to ensure it was working (beeps and LEDs flashing – bingo).  Then proceeded to dump the EEPROM.  The information in the ‘Heart of Darkness’ paper was right.  I now had the MASTER KEYS I’d been trying so hard to retrieve.

pickit2_pic18f_eeprom_access

Note: No keys are shown in the screenshot above!

Hack Complete – Reading iClass Cards

I then turned to Meriac’s CopyClass program (from http://www.openpcd.org/git-view/iclass-security/), entered the keys compiled the program to read my iClass card with HIDs Omnikey 5321 Reader.

I then decided to add to Meriac’s Code to help me to quickly dissect iClass tags and display the meaning of various bytes.

My slightly improved version looks like:

iClass Captured Card

It should auto-detect between 2K and 16K cards, you can use the ‘choose book’ to read different pages/books stored on the card.  And hopefully all  sectors with data should automatically decrypt (provided you have the right key!).  The code is available within PenturaLabs’ github repository:  https://github.com/PenturaLabs/iClassReader

Thanks

At this point I would like to thank Roel Verdult, Flavio D. Garcia, Milosch Meriac and Carl(http://www.proxclone.com); for their patience, quick respones to questions, guidance and support.  Also thanks to my mate who wishes to remain anonymous for supplying the second RW300 RevA Reader.

Read More

Knowing your data rights on the Web – and protecting those rights

Wednesday 12th March was the 25th anniversary of what we now know as the World Wide Web – a date that Tim Berners-Lee, the `inventor’ of the web used to call for an Internet Bill of Rights to be drawn up.  His call follows in the wake of the revelations of Government online surveillance from the past year, and also from the continued growth of online criminal activity.

Berners-Lee called for a `Magna Carta’ Internet Bill of Rights to protect Internet users against snooping and interception of data.  It’s an excellent idea – but also one that relies on trust that all types of organisations, from commerce to Governments, will adhere to the principles of the Bill.

Can businesses afford to take that chance, and trust that others will not try to pry into their intellectual property?  As Pentura MD Steve Smith says here (http://www.scmagazineuk.com/web-inventor-calls-for-internet-bill-of-rights/article/337948/),  “The only way to keep data and IP safe from all types of prying and surveillance – whether from criminals or governments – is to audit what information is critical, and apply appropriate protection to it so it’s safeguarded at rest and in transit.  The Web can’t be trusted, so companies and individuals have to put their own protection measures in place.”

Wednesday 12th March was the 25th anniversary of what we now know as the World Wide Web – a date that Tim Berners-Lee, the `inventor’ of the web used to call for an Internet Bill of Rights to be drawn up.  His call follows in the wake of the revelations of Government online surveillance from the past year, and also from the continued growth of online criminal activity.

Berners-Lee called for a `Magna Carta’ Internet Bill of Rights to protect Internet users against snooping and interception of data.  It’s an excellent idea – but also one that relies on trust that all types of organisations, from commerce to Governments, will adhere to the principles of the Bill.

Can businesses afford to take that chance, and trust that others will not try to pry into their intellectual property?  As Pentura MD Steve Smith says here (http://www.scmagazineuk.com/web-inventor-calls-for-internet-bill-of-rights/article/337948/),  “The only way to keep data and IP safe from all types of prying and surveillance – whether from criminals or governments – is to audit what information is critical, and apply appropriate protection to it so it’s safeguarded at rest and in transit.  The Web can’t be trusted, so companies and individuals have to put their own protection measures in place.”

Read More

Proxmark3 vs Kantech ioProx

Not much is revealed about this type of tag, and only limited data can be found on its data sheet.  Kantech state that readers/cards are compatible with standard 26-bit Wiegand and Kantech Extended Secure Format (XSF). But it is difficult to find any info on the XSF format.  Instead the community has been hard at work collecting cards/fobs and analysing the differences.

From what we have worked out the Kantech ioProx is a RF/64 FSK2a straight modulation.

New Functionality

Demodulation

Simply place your ioProx tag on the antenna and issue the command:

>lf io fskdemod

It should return one answer.  Currently displaying the full 64-bit binary code, the XSF number information printed on the tag, and a hexadecimal representation of the 64-bit binary code for cloning purposes.

Example:

#00000000
#01111000
#01101111
#10100000
#00110000
#10111110
#00011110
#00001011
#XSF(01)BE:03011 (00786fa030be1e0b)

Cloning

Cloning is easy as placing a T55x7 card on the LF antenna and issuing the command:

>lf io clone <UID>

Example:

>lf io clone 00786fa030be1e0b
#Cloning with UID 00786fa0 30be1e0b
#DONE#

UPDATE (21/03/14): The Code

The code is now merged with the Proxmark3 github repo:

git clone https://github.com/Proxmark/proxmark3.git

The Patch

Below is the patch (taken against SVN revision 844):

 Index: armsrc/appmain.c
===================================================================
--- armsrc/appmain.c (revision 844)
+++ armsrc/appmain.c (working copy)
@@ -636,10 +636,16 @@
case CMD_HID_DEMOD_FSK:
CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag
break;
+ case CMD_IO_DEMOD_FSK:
+ CmdIOdemodFSK(1, 0, 0, 1); // Demodulate IO tag
+ break;
+ case CMD_IO_CLONE_TAG: // Clone IO tag by ID to T55x7
+ CopyIOtoT55x7(c->arg[0], c->arg[1], c->d.asBytes[0]);
+ break;
case CMD_HID_SIM_TAG:
- CmdHIDsimTAG(c->arg[0], c->arg[1], 1); // Simulate HID tag by ID
+ CmdHIDsimTAG(c->arg[0], c->arg[1], 1); // Simulate HID tag by ID
break;
- case CMD_HID_CLONE_TAG: // Clone HID tag by ID to T55x7
+ case CMD_HID_CLONE_TAG: // Clone HID tag by ID to T55x7
CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]);
break;
case CMD_EM410X_WRITE_TAG:
Index: armsrc/apps.h
===================================================================
--- armsrc/apps.h (revision 844)
+++ armsrc/apps.h (working copy)
@@ -117,6 +117,8 @@
void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
+void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
+void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an ioProx card to T5557/T5567
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
Index: armsrc/lfops.c
===================================================================
--- armsrc/lfops.c (revision 844)
+++ armsrc/lfops.c (working copy)
@@ -807,6 +807,264 @@
}
}

+void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
+{
+ uint8_t *dest = (uint8_t *)BigBuf;
+ int m=0, n=0, i=0, idx=0, lastval=0;
+ int found=0;
+ uint32_t code=0, code2=0;
+ //uint32_t hi2=0, hi=0, lo=0;
+
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+
+ // Connect the A/D to the peak-detected low-frequency path.
+ SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+
+ // Give it a bit of time for the resonant antenna to settle.
+ SpinDelay(50);
+
+ // Now set up the SSC to get the ADC samples that are now streaming at us.
+ FpgaSetupSsc();
+
+ for(;;) {
+ WDT_HIT();
+ if (ledcontrol)
+ LED_A_ON();
+ if(BUTTON_PRESS()) {
+ DbpString("Stopped");
+ if (ledcontrol)
+ LED_A_OFF();
+ return;
+ }
+
+ i = 0;
+ m = sizeof(BigBuf);
+ memset(dest,128,m);
+ for(;;) {
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+ AT91C_BASE_SSC->SSC_THR = 0x43;
+ if (ledcontrol)
+ LED_D_ON();
+ }
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+ // we don't care about actual value, only if it's more or less than a
+ // threshold essentially we capture zero crossings for later analysis
+ if(dest[i] < 127) dest[i] = 0; else dest[i] = 1; + i++; + if (ledcontrol) + LED_D_OFF(); + if(i >= m) {
+ break;
+ }
+ }
+ }
+
+ // FSK demodulator
+
+ // sync to first lo-hi transition
+ for( idx=1; idx<m; idx++) {
+ if (dest[idx-1]<dest[idx])
+ lastval=idx;
+ break;
+ }
+ WDT_HIT();
+
+ // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
+ // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
+ // between 7 to 11 cycles so fuzz it by treat anything + for( i=0; idx<m; idx++) {
+ if (dest[idx-1]<dest[idx]) {
+ dest[i]=idx-lastval;
+ if (dest[i] <= 8) {
+ dest[i]=1;
+ } else {
+ dest[i]=0;
+ }
+
+ lastval=idx;
+ i++;
+ }
+ }
+ m=i;
+ WDT_HIT();
+
+ // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
+ lastval=dest[0];
+ idx=0;
+ i=0;
+ n=0;
+ for( idx=0; idx<m; idx++) {
+ if (dest[idx]==lastval) {
+ n++;
+ } else {
+ // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,
+ // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets
+ // swallowed up by rounding
+ // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding
+ // special start of frame markers use invalid manchester states (no transitions) by using sequences
+ // like 111000
+ if (dest[idx-1]) {
+ n=(n+1)/7; // fc/8 in sets of 7
+ } else {
+ n=(n+1)/6; // fc/10 in sets of 6
+ }
+ switch (n) { // stuff appropriate bits in buffer
+ case 0:
+ case 1: // one bit
+ dest[i++]=dest[idx-1]^1;
+ //Dbprintf("%d",dest[idx-1]);
+ break;
+ case 2: // two bits
+ dest[i++]=dest[idx-1]^1;
+ dest[i++]=dest[idx-1]^1;
+ //Dbprintf("%d",dest[idx-1]);
+ //Dbprintf("%d",dest[idx-1]);
+ break;
+ case 3: // 3 bit start of frame markers
+ for(int j=0; j<3; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 4:
+ for(int j=0; j<4; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 5:
+ for(int j=0; j<5; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 6:
+ for(int j=0; j<6; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 7:
+ for(int j=0; j<7; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 8:
+ for(int j=0; j<8; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 9:
+ for(int j=0; j<9; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 10:
+ for(int j=0; j<10; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 11:
+ for(int j=0; j<11; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 12:
+ for(int j=0; j<12; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ default: // this shouldn't happen, don't stuff any bits
+ //Dbprintf("%d",dest[idx-1]);
+ break;
+ }
+ n=0;
+ lastval=dest[idx];
+ }
+ }//end for
+ /*for(int j=0; j<64;j+=8){
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[j],dest[j+1],dest[j+2],dest[j+3],dest[j+4],dest[j+5],dest[j+6],dest[j+7]);
+ }
+ Dbprintf("n");*/
+ m=i;
+ WDT_HIT();
+
+ for( idx=0; idx<m-9; idx++) {
+ if ( !(dest[idx]) && !(dest[idx+1]) && !(dest[idx+2]) && !(dest[idx+3]) && !(dest[idx+4]) && !(dest[idx+5]) && !(dest[idx+6]) && !(dest[idx+7])
&& !(dest[idx+8])&& (dest[idx+9])){
+ found=1;
+ //idx+=9;
+ if (found) {
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+8], dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+16],dest[idx+17],dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+24],dest[idx+25],dest[idx+26],dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35],dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44],dest[idx+45],dest[idx+46],dest[idx+47]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53],dest[idx+54],dest[idx+55]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
+
+ short version='x00';
+ char unknown='x00';
+ uint16_t number=0;
+ for(int j=14;j<18;j++){
+ //Dbprintf("%d",dest[idx+j]);
+ version <<=1;
+ if (dest[idx+j]) version |= 1;
+ }
+ for(int j=19;j<27;j++){
+ //Dbprintf("%d",dest[idx+j]);
+ unknown <<=1;
+ if (dest[idx+j]) unknown |= 1;
+ }
+ for(int j=36;j<45;j++){
+ //Dbprintf("%d",dest[idx+j]);
+ number <<=1;
+ if (dest[idx+j]) number |= 1;
+ }
+ for(int j=46;j<53;j++){
+ //Dbprintf("%d",dest[idx+j]);
+ number <<=1;
+ if (dest[idx+j]) number |= 1;
+ }
+ for(int j=0; j<32; j++){
+ code <<=1;
+ if(dest[idx+j]) code |= 1;
+ }
+ for(int j=32; j<64; j++){
+ code2 <<=1;
+ if(dest[idx+j]) code2 |= 1;
+ }
+
+ Dbprintf("XSF(%02d)%02x:%d (%08x%08x)",version,unknown,number,code,code2);
+ if (ledcontrol)
+ LED_D_OFF();
+ }
+ // if we're only looking for one tag
+ if (findone){
+ //*high = hi;
+ //*low = lo;
+ LED_A_OFF();
+ return;
+ }
+
+ //hi=0;
+ //lo=0;
+ found=0;
+ }
+
+ }
+ }
+ WDT_HIT();
+}
+
/*------------------------------
* T5555/T5557/T5567 routines
*------------------------------
@@ -1166,6 +1424,26 @@
DbpString("DONE!");
}

+void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT)
+{
+ int data1=0, data2=0; //up to six blocks for long format
+
+ data1 = hi; // load preamble
+ data2 = lo;
+
+ LED_D_ON();
+ // Program the data blocks for supplied ID
+ // and the block 0 for HID format
+ T55xxWriteBlock(data1,1,0,0);
+ T55xxWriteBlock(data2,2,0,0);
+
+ //Config Block
+ T55xxWriteBlock(0x00147040,0,0,0);
+ LED_D_OFF();
+
+ DbpString("DONE!");
+}
+
// Define 9bit header for EM410x tags
#define EM410X_HEADER 0x1FF
#define EM410X_ID_LENGTH 40
Index: client/Makefile
===================================================================
--- client/Makefile (revision 844)
+++ client/Makefile (working copy)
@@ -75,6 +75,7 @@
cmdhw.c 
cmdlf.c 
cmdlfhid.c 
+ cmdlfio.c 
cmdlfem4x.c 
cmdlfhitag.c 
cmdlfti.c 
Index: client/cmdlf.c
===================================================================
--- client/cmdlf.c (revision 844)
+++ client/cmdlf.c (working copy)
@@ -27,6 +27,7 @@
#include "cmdlfhitag.h"
#include "cmdlft55xx.h"
#include "cmdlfpcf7931.h"
+#include "cmdlfio.h"

static int CmdHelp(const char *Cmd);

@@ -128,7 +129,7 @@
RepaintGraphWindow();
return 0;
}
-
+
int CmdIndalaDemod(const char *Cmd)
{
// Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
@@ -532,6 +533,7 @@
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
+ {"io", CmdLFIO, 1, "{ ioProx tags... }"},
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
{"indalaclone", CmdIndalaClone, 1, " ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
{"read", CmdLFRead, 0, "['h'|] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
Index: include/usb_cmd.h
===================================================================
--- include/usb_cmd.h (revision 844)
+++ include/usb_cmd.h (working copy)
@@ -79,6 +79,8 @@
#define CMD_PCF7931_READ 0x0217
#define CMD_EM4X_READ_WORD 0x0218
#define CMD_EM4X_WRITE_WORD 0x0219
+#define CMD_IO_DEMOD_FSK 0x021A
+#define CMD_IO_CLONE_TAG 0x021B
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */

// For the 13.56 MHz tags

Not much is revealed about this type of tag, and only limited data can be found on its data sheet.  Kantech state that readers/cards are compatible with standard 26-bit Wiegand and Kantech Extended Secure Format (XSF). But it is difficult to find any info on the XSF format.  Instead the community has been hard at work collecting cards/fobs and analysing the differences.

From what we have worked out the Kantech ioProx is a RF/64 FSK2a straight modulation.

New Functionality

Demodulation

Simply place your ioProx tag on the antenna and issue the command:

>lf io fskdemod

It should return one answer.  Currently displaying the full 64-bit binary code, the XSF number information printed on the tag, and a hexadecimal representation of the 64-bit binary code for cloning purposes.

Example:

#00000000
#01111000
#01101111
#10100000
#00110000
#10111110
#00011110
#00001011
#XSF(01)BE:03011 (00786fa030be1e0b)

Cloning

Cloning is easy as placing a T55x7 card on the LF antenna and issuing the command:

>lf io clone <UID>

Example:

>lf io clone 00786fa030be1e0b
#Cloning with UID 00786fa0 30be1e0b
#DONE#

UPDATE (21/03/14): The Code

The code is now merged with the Proxmark3 github repo:

git clone https://github.com/Proxmark/proxmark3.git

The Patch

Below is the patch (taken against SVN revision 844):

 Index: armsrc/appmain.c
===================================================================
--- armsrc/appmain.c (revision 844)
+++ armsrc/appmain.c (working copy)
@@ -636,10 +636,16 @@
case CMD_HID_DEMOD_FSK:
CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag
break;
+ case CMD_IO_DEMOD_FSK:
+ CmdIOdemodFSK(1, 0, 0, 1); // Demodulate IO tag
+ break;
+ case CMD_IO_CLONE_TAG: // Clone IO tag by ID to T55x7
+ CopyIOtoT55x7(c->arg[0], c->arg[1], c->d.asBytes[0]);
+ break;
case CMD_HID_SIM_TAG:
- CmdHIDsimTAG(c->arg[0], c->arg[1], 1); // Simulate HID tag by ID
+ CmdHIDsimTAG(c->arg[0], c->arg[1], 1); // Simulate HID tag by ID
break;
- case CMD_HID_CLONE_TAG: // Clone HID tag by ID to T55x7
+ case CMD_HID_CLONE_TAG: // Clone HID tag by ID to T55x7
CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]);
break;
case CMD_EM410X_WRITE_TAG:
Index: armsrc/apps.h
===================================================================
--- armsrc/apps.h (revision 844)
+++ armsrc/apps.h (working copy)
@@ -117,6 +117,8 @@
void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
+void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
+void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an ioProx card to T5557/T5567
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an HID card to T5557/T5567
void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
Index: armsrc/lfops.c
===================================================================
--- armsrc/lfops.c (revision 844)
+++ armsrc/lfops.c (working copy)
@@ -807,6 +807,264 @@
}
}

+void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
+{
+ uint8_t *dest = (uint8_t *)BigBuf;
+ int m=0, n=0, i=0, idx=0, lastval=0;
+ int found=0;
+ uint32_t code=0, code2=0;
+ //uint32_t hi2=0, hi=0, lo=0;
+
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+
+ // Connect the A/D to the peak-detected low-frequency path.
+ SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+
+ // Give it a bit of time for the resonant antenna to settle.
+ SpinDelay(50);
+
+ // Now set up the SSC to get the ADC samples that are now streaming at us.
+ FpgaSetupSsc();
+
+ for(;;) {
+ WDT_HIT();
+ if (ledcontrol)
+ LED_A_ON();
+ if(BUTTON_PRESS()) {
+ DbpString("Stopped");
+ if (ledcontrol)
+ LED_A_OFF();
+ return;
+ }
+
+ i = 0;
+ m = sizeof(BigBuf);
+ memset(dest,128,m);
+ for(;;) {
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+ AT91C_BASE_SSC->SSC_THR = 0x43;
+ if (ledcontrol)
+ LED_D_ON();
+ }
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+ // we don't care about actual value, only if it's more or less than a
+ // threshold essentially we capture zero crossings for later analysis
+ if(dest[i] < 127) dest[i] = 0; else dest[i] = 1; + i++; + if (ledcontrol) + LED_D_OFF(); + if(i >= m) {
+ break;
+ }
+ }
+ }
+
+ // FSK demodulator
+
+ // sync to first lo-hi transition
+ for( idx=1; idx<m; idx++) {
+ if (dest[idx-1]<dest[idx])
+ lastval=idx;
+ break;
+ }
+ WDT_HIT();
+
+ // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
+ // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
+ // between 7 to 11 cycles so fuzz it by treat anything + for( i=0; idx<m; idx++) {
+ if (dest[idx-1]<dest[idx]) {
+ dest[i]=idx-lastval;
+ if (dest[i] <= 8) {
+ dest[i]=1;
+ } else {
+ dest[i]=0;
+ }
+
+ lastval=idx;
+ i++;
+ }
+ }
+ m=i;
+ WDT_HIT();
+
+ // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
+ lastval=dest[0];
+ idx=0;
+ i=0;
+ n=0;
+ for( idx=0; idx<m; idx++) {
+ if (dest[idx]==lastval) {
+ n++;
+ } else {
+ // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,
+ // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets
+ // swallowed up by rounding
+ // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding
+ // special start of frame markers use invalid manchester states (no transitions) by using sequences
+ // like 111000
+ if (dest[idx-1]) {
+ n=(n+1)/7; // fc/8 in sets of 7
+ } else {
+ n=(n+1)/6; // fc/10 in sets of 6
+ }
+ switch (n) { // stuff appropriate bits in buffer
+ case 0:
+ case 1: // one bit
+ dest[i++]=dest[idx-1]^1;
+ //Dbprintf("%d",dest[idx-1]);
+ break;
+ case 2: // two bits
+ dest[i++]=dest[idx-1]^1;
+ dest[i++]=dest[idx-1]^1;
+ //Dbprintf("%d",dest[idx-1]);
+ //Dbprintf("%d",dest[idx-1]);
+ break;
+ case 3: // 3 bit start of frame markers
+ for(int j=0; j<3; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 4:
+ for(int j=0; j<4; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 5:
+ for(int j=0; j<5; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 6:
+ for(int j=0; j<6; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 7:
+ for(int j=0; j<7; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 8:
+ for(int j=0; j<8; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 9:
+ for(int j=0; j<9; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 10:
+ for(int j=0; j<10; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 11:
+ for(int j=0; j<11; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ case 12:
+ for(int j=0; j<12; j++){
+ dest[i++]=dest[idx-1]^1;
+ // Dbprintf("%d",dest[idx-1]);
+ }
+ break;
+ default: // this shouldn't happen, don't stuff any bits
+ //Dbprintf("%d",dest[idx-1]);
+ break;
+ }
+ n=0;
+ lastval=dest[idx];
+ }
+ }//end for
+ /*for(int j=0; j<64;j+=8){
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[j],dest[j+1],dest[j+2],dest[j+3],dest[j+4],dest[j+5],dest[j+6],dest[j+7]);
+ }
+ Dbprintf("n");*/
+ m=i;
+ WDT_HIT();
+
+ for( idx=0; idx<m-9; idx++) {
+ if ( !(dest[idx]) && !(dest[idx+1]) && !(dest[idx+2]) && !(dest[idx+3]) && !(dest[idx+4]) && !(dest[idx+5]) && !(dest[idx+6]) && !(dest[idx+7])
&& !(dest[idx+8])&& (dest[idx+9])){
+ found=1;
+ //idx+=9;
+ if (found) {
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+8], dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+16],dest[idx+17],dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+24],dest[idx+25],dest[idx+26],dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35],dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44],dest[idx+45],dest[idx+46],dest[idx+47]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53],dest[idx+54],dest[idx+55]);
+ Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
+
+ short version='x00';
+ char unknown='x00';
+ uint16_t number=0;
+ for(int j=14;j<18;j++){
+ //Dbprintf("%d",dest[idx+j]);
+ version <<=1;
+ if (dest[idx+j]) version |= 1;
+ }
+ for(int j=19;j<27;j++){
+ //Dbprintf("%d",dest[idx+j]);
+ unknown <<=1;
+ if (dest[idx+j]) unknown |= 1;
+ }
+ for(int j=36;j<45;j++){
+ //Dbprintf("%d",dest[idx+j]);
+ number <<=1;
+ if (dest[idx+j]) number |= 1;
+ }
+ for(int j=46;j<53;j++){
+ //Dbprintf("%d",dest[idx+j]);
+ number <<=1;
+ if (dest[idx+j]) number |= 1;
+ }
+ for(int j=0; j<32; j++){
+ code <<=1;
+ if(dest[idx+j]) code |= 1;
+ }
+ for(int j=32; j<64; j++){
+ code2 <<=1;
+ if(dest[idx+j]) code2 |= 1;
+ }
+
+ Dbprintf("XSF(%02d)%02x:%d (%08x%08x)",version,unknown,number,code,code2);
+ if (ledcontrol)
+ LED_D_OFF();
+ }
+ // if we're only looking for one tag
+ if (findone){
+ //*high = hi;
+ //*low = lo;
+ LED_A_OFF();
+ return;
+ }
+
+ //hi=0;
+ //lo=0;
+ found=0;
+ }
+
+ }
+ }
+ WDT_HIT();
+}
+
/*------------------------------
* T5555/T5557/T5567 routines
*------------------------------
@@ -1166,6 +1424,26 @@
DbpString("DONE!");
}

+void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT)
+{
+ int data1=0, data2=0; //up to six blocks for long format
+
+ data1 = hi; // load preamble
+ data2 = lo;
+
+ LED_D_ON();
+ // Program the data blocks for supplied ID
+ // and the block 0 for HID format
+ T55xxWriteBlock(data1,1,0,0);
+ T55xxWriteBlock(data2,2,0,0);
+
+ //Config Block
+ T55xxWriteBlock(0x00147040,0,0,0);
+ LED_D_OFF();
+
+ DbpString("DONE!");
+}
+
// Define 9bit header for EM410x tags
#define EM410X_HEADER 0x1FF
#define EM410X_ID_LENGTH 40
Index: client/Makefile
===================================================================
--- client/Makefile (revision 844)
+++ client/Makefile (working copy)
@@ -75,6 +75,7 @@
cmdhw.c 
cmdlf.c 
cmdlfhid.c 
+ cmdlfio.c 
cmdlfem4x.c 
cmdlfhitag.c 
cmdlfti.c 
Index: client/cmdlf.c
===================================================================
--- client/cmdlf.c (revision 844)
+++ client/cmdlf.c (working copy)
@@ -27,6 +27,7 @@
#include "cmdlfhitag.h"
#include "cmdlft55xx.h"
#include "cmdlfpcf7931.h"
+#include "cmdlfio.h"

static int CmdHelp(const char *Cmd);

@@ -128,7 +129,7 @@
RepaintGraphWindow();
return 0;
}
-
+
int CmdIndalaDemod(const char *Cmd)
{
// Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
@@ -532,6 +533,7 @@
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
+ {"io", CmdLFIO, 1, "{ ioProx tags... }"},
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
{"indalaclone", CmdIndalaClone, 1, " ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
{"read", CmdLFRead, 0, "['h'|] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
Index: include/usb_cmd.h
===================================================================
--- include/usb_cmd.h (revision 844)
+++ include/usb_cmd.h (working copy)
@@ -79,6 +79,8 @@
#define CMD_PCF7931_READ 0x0217
#define CMD_EM4X_READ_WORD 0x0218
#define CMD_EM4X_WRITE_WORD 0x0219
+#define CMD_IO_DEMOD_FSK 0x021A
+#define CMD_IO_CLONE_TAG 0x021B
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */

// For the 13.56 MHz tags
Read More

The data breach earthquake

The aftershocks of a data breach can be catastrophic to a business, whether it’s the loss of sensitive information such as customer records, or the business’ intellectual property finding its way into the wrong hands.  What is certain, is it will have a detrimental impact to the bottom line in one way or another.

The actual cost is often difficult to quantify. Especially when it comes to intellectual property as it is difficult to know how the information has been used and what the opportunity and potential may have been. However, there are occasions when the cost is all too transparent.

This was demonstrated last December, when during the important Christmas shopping period, Target reported a data breach that had compromised the details of up to 110 million customers.  Last week, Target announced its Q4 figures which all too clearly told the story of the devastating aftermath of this data breach – just about every key metric was down on the same period last year – and its profits and share price had fallen significantly. Already, $61m can be attributed directly to the cost of the breach, and analysts are speculating that it could cost towards $1bn in the end, when items such as notifying those affected, credit checks, insurance and so on are factored in.

The recent Barclays Bank customer records leak also highlights the financial consequences as the bank faces penalties from the Financial Conduct Authority (FCA), which can impose unlimited fines, and the Information Commissioner’s Office (ICO), which can impose fines of up to £500,000.  For many businesses the financial impact may not be on the same scale, but still, when the economic conditions are challenging to start with, what business can afford to throw money away on a data breach that could have been avoided if a data loss prevention strategy had been in place?

The aftershocks of a data breach can be catastrophic to a business, whether it’s the loss of sensitive information such as customer records, or the business’ intellectual property finding its way into the wrong hands.  What is certain, is it will have a detrimental impact to the bottom line in one way or another.

The actual cost is often difficult to quantify. Especially when it comes to intellectual property as it is difficult to know how the information has been used and what the opportunity and potential may have been. However, there are occasions when the cost is all too transparent.

This was demonstrated last December, when during the important Christmas shopping period, Target reported a data breach that had compromised the details of up to 110 million customers.  Last week, Target announced its Q4 figures which all too clearly told the story of the devastating aftermath of this data breach – just about every key metric was down on the same period last year – and its profits and share price had fallen significantly. Already, $61m can be attributed directly to the cost of the breach, and analysts are speculating that it could cost towards $1bn in the end, when items such as notifying those affected, credit checks, insurance and so on are factored in.

The recent Barclays Bank customer records leak also highlights the financial consequences as the bank faces penalties from the Financial Conduct Authority (FCA), which can impose unlimited fines, and the Information Commissioner’s Office (ICO), which can impose fines of up to £500,000.  For many businesses the financial impact may not be on the same scale, but still, when the economic conditions are challenging to start with, what business can afford to throw money away on a data breach that could have been avoided if a data loss prevention strategy had been in place?

Read More

JOIN NEWSLETTER

Know What We're Up To!