RESEARCH | December 17, 2015

(In)secure iOS Mobile Banking Apps – 2015 Edition

Two years ago, I decided to conduct research in order to obtain a global view of the state of security of mobile banking apps from some important banks. In this blog post, I will present my latest results to show how the security of the same mobile banking apps has evolved.

(more…)

INSIGHTS | August 25, 2015

Money may grow on trees

Sometimes when buying something that costs $0.99 USD (99 cents) or $1.01 USD (one dollar and one cent), you may pay an even dollar. Either you or the cashier may not care about the remaining penny, and so one of you takes a small loss or profit.

 

Rounding at the cash register is a common practice, just as it is in programming languages when dealing with very small or very large numbers. I will describe here how an attacker can make a profit when dealing with the rounding mechanisms of programming languages.
 
Lack of precision in numbers

IEEE 754 standard has defined floating point numbers for more than 30 years. The requirements that guided the formulation of the standard for binary floating-point arithmetic provided for the development of very high-precision arithmetic.

 

The standard defines how operations with floating point numbers should be performed, and also defines standard behavior for abnormal operations. It identifies five possible types of floating point exceptions: invalid operation (highest priority), division by zero, overflow, underflow, and inexact (lowest priority).

 

We will explore what happens when inexact floating point exceptions are triggered. The rounded result of a valid operation can be different from the real (and sometimes infinitely precise) result and certain operations may go unnoticed.
 
Rounding
Rounding takes an exact number and, if necessary, modifies it to fit in the destination’s format. Normally, programming languages do not alert for the inexact exception and instead just deliver the rounded value. Nevertheless, documentation for programming languages contains some warnings about this:

 

To exemplify this matter, this is how the number 0.1 looks internally in Python:

 

The decimal value 0.1 cannot be represented precisely when using binary notation, since it is an infinite number in base 2. Python will round the previous number to 0.1 before showing the value.
 
Salami slicing the decimals

Salami slicing refers to a series of small actions that will produce a result that would be impossible to perform all at once. In this case, we will grab the smallest amount of decimals that are being ignored by the programming language and use that for profit.

 

Let’s start to grab some decimals in a way that goes unnoticed by the programming language. Certain calculations will trigger more obvious differences using certain specific values. For example, notice what happens when using v8 (Google’s open source JavaScript engine) to add the values 0.1 plus 0.2:

 

Perhaps we could take some of those decimals without JavaScript noticing:

 

 

 

But what happens if we are greedy? How much can we take without JavaScript noticing?

 
 
That’s interesting; we learned that it is even possible to take more than what was shown, but no more than 0.00000000000000008 from that operation before JavaScript notices.
I created a sample bank application to explain this, pennies.js:
 
// This is used to wire money
function wire(deposit, money, withdraw) {
  account[deposit] += money;
  account[withdraw] -= money;
  if(account[withdraw]<0)
    return 1; // Error! The account can not have a negative balance
  return 0;
}
 
// This is used to print the balance
function print_balance(time) {
  print(“——————————————–“);
  print(” The balance of the bank accounts is:”);
  print(” Account 0: “+account[0]+” u$s”);
  print(” Account 1: “+account[1]+” u$s (profit)”);
  print(” Overall money: “+(account[0]+account[1]))
  print(“——————————————–“);
  if(typeof time !== ‘undefined’) {
     print(” Estimated daily profit: “+( (60*60*24/time) * account[1] ) );
     print(“——————————————–“);
  }
}
 
// This is used to set the default initial values
function reset_values() {
  account[0] = initial_deposit;
  account[1] = 0; // I will save my profit here 
}
 
account = new Array();
initial_deposit = 1000000;
profit = 0
print(“n1) Searching for the best profit”);
for(i = 0.000000000000000001; i < 0.1; i+=0.0000000000000000001) {
  reset_values();
  wire(1, i, 0); // I will transfer some cents from the account 0 to the account 1
  if(account[0]==initial_deposit && i>profit) {
    profit = i;
 //   print(“I can grab “+profit.toPrecision(21));
  } else {
    break;
  }
}
print(”   Found: “+profit.toPrecision(21));
print(“n2) Let’s start moving some money:”);
 
reset_values();
 
start = new Date().getTime() / 1000;
for (j = 0; j < 10000000000; j++) {
  for (i = 0; i < 1000000000; i++) { 
    wire(1, profit, 0); // I will transfer some cents from the account 0 to the account 1
  }
  finish = new Date().getTime() / 1000;
  print_balance(finish-start);
}
 

The attack against it will have two phases. In the first phase, we will determine the maximum amount of decimals that we are allowed to take from an account before the language notices something is missing. This amount is related to the value from which we are we taking: the higher the value, the higher the amount of decimals. Our Bank Account 0 will have $1,000,000 USD to start with, and we will deposit our profits to a secondary Account 1:

 

Due to the decimals being silently shifted to Account 1, the bank now believes that it has more money than it actually has.

 

Another possibility to abuse the loss of precision is what happens when dealing with large numbers. The problem becomes visible when using at least 17 digits.
 

Now, the sample attack application will occur on a crypto currency, fakecoin.js:

 

 
// This is used to wire money
function wire(deposit, money, withdraw) {
  account[deposit] += money;
  account[withdraw] -= money;
  if(account[withdraw]<0) {
    return 1; // Error! The account can not have a negative balance
  }
  return 0;
}
 
// This is used to print the balance
function print_balance(time) {
  print(“————————————————-“);
  print(” The general balance is:”);
  print(” Crypto coin:  “+crypto_coin);
  print(” Crypto value: “+crypto_value);
  print(” Crypto cash:  “+(account[0]*crypto_value)+” u$s”);
  print(” Account 0: “+account[0]+” coins”);
  print(” Account 1: “+account[1]+” coins”);
  print(” Overall value: “+( ( account[0] + account[1] ) * crypto_value )+” u$s”)
  print(“————————————————-“);
  if(typeof time !== ‘undefined’) {
     seconds_in_a_day = 60*60*24;
     print(” Estimated daily profit: “+( (seconds_in_a_day/time) * account[1] * crypto_value) +” u$s”);
     print(“————————————————-n”);
  }
}
 
// This is used to set the default initial values
function reset_values() {
  account[0] = initial_deposit;
  account[1] = 0; // profit
}
 
// My initial money
initial_deposit = 10000000000000000;
crypto_coin = “Fakecoin”
crypto_value = 0.00000000011;
 
// Here I have my bank accounts defined
account = new Array();
 
print(“n1) Searching for the best profit”);
profit = 0
for (j = 1; j < initial_deposit; j+=1) {
  reset_values();
  wire(1, j, 0); // I will transfer a few cents from the account 0 to the account 1
  if(account[0]==initial_deposit && j > profit) {
    profit = j;
  } else {
    break;
  }
}
print(”   Found: “+profit);
reset_values();
start = new Date().getTime() / 1000;
print(“n2) Let’s start moving some money”);
for (j = 0; j < 10000000000; j++) {
  for (i = 0; i < 1000000000; i++) { 
    wire(1, profit, 0); // I will transfer my 29 cents from the account 0 to the account 1
  }
  finish = new Date().getTime() / 1000;
  print_balance(finish-start);
}
 
 
We will buy 10000000000000000 units of Fakecoin (with each coin valued at $0.00000000011 USD) for a total value of $1,100,000 USD. We will transfer one Fakecoin at the time from Account 0 to a second account that will hold our profits (Account 1). JavaScript will not notice the missing Fakecoin from Account 0, and will allow us to profit a total of approximately $2,300 USD per day:

Depending on the implementation, a hacker can used either float numbers or large numbers to generate money out of thin air.
 
Conclusion
In conclusion, programmers can avoid inexact floating point exceptions with some best practices:
  • If you rely on values that use decimal numbers, use specialized variables like BigInteger in Java.
  • Do not allow values larger than 16 digits to be stored in variables and truncate decimals, or
  • Use libraries that rely on quadruple precision (that is, twice the amount of regular precision).

 

INSIGHTS | October 28, 2013

Hacking a counterfeit money detector for fun and non-profit

In Spain we have a saying “Hecha la ley, hecha la trampa” which basically means there will always be a way to circumvent a restriction. In fact, that is pretty much what hacking is all about.

 

It seems the idea of ‘counterfeiting’ appeared at the same time as legitimate money. The Wikipedia page for Counterfeit money  is a fascinating read that helps explain its effects.

 

http://en.wikipedia.org/wiki/Counterfeit_money

 

Nowadays every physical currency implements security measures to prevent counterfeiting. Some counterfeits can be detected with a naked eye, while others need specific devices or procedures to be identified. In order to help employees, counterfeit money detectors can be found in places that accept cash, including shops, malls, postal offices, banks, and gas stations.

 

Recently I took a look at one of these devices, Secureuro. I chose this device because it is widely used in Spain, and its firmware is freely available to download.
http://www.securytec.es/Informacion/clientes-de-secureuro

 

As usual, the first thing I did when approaching a static analysis of a device of this kind was to collect as much information as possible. We should look for anything that could help us to understand how the target works at all levels.

 

In this case I used the following sources:
Youtube
http://www.youtube.com/user/EuroSecurytec
I found some videos where the vendor details how to use the device. This let me analyze the behavior of the device, such as when an LED turns on, when a sound plays, and what messages are displayed. This knowledge is very helpful for understanding the underlying logic when analyzing the assembler later on.
 
 
Vendor Material
Technical specs, manuals, software, firmware … [1] [2] [3] See references.
The following document provides some insights into the device’s security http://www.secureuro.com/secureuro/ingles/MANUALINGLES2006.pdf (resource no longer available)
Unfortunately, some of these claims are not completely true and others are simply false. It is possible to understand how Secureuro works; we can access the firmware and EEPROM without even needing hardware hacking. Also, there is no encryption system protecting the firmware.
Before we start discussing the technical details, I would like to clarify that we are not disclosing any trick that could help criminals to bypass the device ‘as is’. My intention is not to forge a banknote that could pass as legitimate, that is a criminal offense. My sole purpose is to explain how I identified the code behind the validation in order to create ‘trojanized’ firmware that accepts even a simple piece of paper as a valid currency. We are not exploiting a vulnerability in the device, just a design feature.
 
 
Analyzing the Firmware
This is the software that downloads the firmware into the device. The firmware file I downloaded from the vendor’s website contains 128K of data that will be flashed to the ATMEGA128 microcontroller. So I can directly load it into IDA, although I do not have access to the EEPROM yet.
 
Entry Points
A basic approach to dealing with this kind of firmware is to identify some elements or entry points that can leveraged to look for interesting pieces of code.
A minimal set includes:
 
Interruption Vector 
  1.  RESET == Main Entry Point
  2.  TIMERs
  3.  UARTs
  4.  SPI
Mnemonics
  1.  LPM (Load Program Memory)
  2.  SPM (Store Program Memory)
  3.  IN
  4.  OUT
Registers
 
ADCL: The ADC Data Register Low
ADCH: The ADC Data Register High
ADCSRA: ADC Control and Status Register
ADMUX: ADC Multiplexer Selection Register
ACSR: Analog Comparator Control and Status
UBRR0L: USART Baud Rate Register
UCSR0B: USART Control and Status Register
UCSR0A: USART Control and Status Register
UDR0: USART I/O Data Register
SPCR: SPI Control Register
SPSR: SPI Status Register
SPDR: SPI Data Register
EECR: EEPROM Control Register
EEDR: EEPROM Data Register
EEARL: EEPROM Address Register Low
EEARH: EEPROM Address Register High
OCR2: Output Compare Register
TCNT2: Timer/Counter Register
TCCR2: Timer/Counter Control Register
OCR1BL: Output Compare Register B Low
OCR1BH: Output Compare Register B High
OCR1AL: Output Compare Register A Low
OCR1AH: Output Compare Register A High
TCNT1L: Counter Register Low Byte
TCNT1H: Counter Register High Byte
TCCR1B: Timer/Counter1 Control Register B
TCCR1A: Timer/Counter1 Control Register A
OCR0: Timer/Counter0 Output Compare Register
TCNT0: Timer/Counter0
TCCR0: Timer/Counter Control Register
TIFR: Timer/Counter Interrupt Flag Register
TIMSK: Timer/Counter Interrupt Mask Register
Using this information, we should reconstruct some firmware functions to make it more reverse engineering friendly.
First, I try to identify the Main, following the flow at the RESET ISR. This step is pretty straightforward.
As an example of collecting information based on the mnemonics, we identify a function reading from flash memory, which is renamed to ‘readFromFlash‘. Its cross-references will provide valuable information.
By finding the references to the registers involved in EEPROM operations I come across the following functions ‘sub_CFC‘ and ‘sub_CF3‘:

 

The first routine reads from an arbitrary address in the EEPROM. The second routine writes to the EEPROM. I rename ‘sub_CFC‘ to ‘EEPROM_read‘ and ‘sub_CF3‘ to ‘EEPROM_write‘. These two functions are very useful, and provide us with important clues.
Now that our firmware looks like a little bit more friendly, we focus on the implemented functionalities. The documentation I collected states that this device has been designed to allow communications with a computer; therefore we should start by taking a look at the UART ISRs.
Tip: You can look for USART configuration registers UCSR0B, UBRR0… to see how it is configured. 
USART0_RX
It is definitely interesting, when receiving a ‘J’ (0x49) character it initializes the usual procedure to send data through the serial interface. It checks UDRE until it is ready and then sends outs bytes through UDR0. Going down a little bit I find the following piece of code
It is using the function to read from the EEPROM I identified earlier. It seems that if we want to understand what is going on we will have to analyze the other functions involved in this basic block, ‘sub_3CBB‘ and ‘sub_3C9F‘.
 
SUB_3CBB
This function is receiving two parameters, a length (r21:r20) and a memory address (r17:r16), and transmitting the n bytes located at the memory address through UDR0. It basically sends n bytes through the serial interface.
I rename ‘sub_3CBB’ to ‘dumpMemToSerial‘. So  this function being called in the following way: dumpMemToSerial(0xc20,9). What’s at address 0xc20? Apparently nothing that makes sense to dump out. I must be missing something here. What can we do? Let’s analyze the stub code the linker puts at the RESET ISR, just before the ‘Main’ entry point. That code usually contains routines for custom memory initialization.
Good enough, ‘sub_4D02‘ is a memory copy function from flash to SRAM. It uses LPM so it demonstrates how important it is to check specific mnemonics to discover juicy functions.
Now take a look at the parameters, at ROM:4041 it is copying 0x2BD bytes (r21:r20) from 0x80A1 (r31:r30) to 0xBC2 (r17:r16). If we go to 0x80A1 in the firmware file, we will find a string table!
Knowing that 0xBC2 has the string table above, my previous call makes much more sense now: dumpMemToSerial(0xc20,9) => 0xC20 – 0xBC2 = 0x5E
String Table (0x80A1) + 0x5E == “#RESETS”
The remaining function to analyze is ‘sub_3C9F‘, which is basically formatting a byte to its ASCII representation to send it out through the serial interface. I rename it ‘hex2ascii
So, according to the code, if we send ‘J’ to the device, we should be receiving some statistics. This matches what I read in the documentation.
http://www.secureuro.com/secureuro/ingles/MANUALINGLES2006.pdf
Now this basic block seems much clearer. It is ‘printing’ some internal statistics.
“#RESETS: 000000” where 000000 is a three byte counter
(“BILLETES” means “BANKNOTES” in Spanish)
“#BILLETES: 000000 “
(“NO VALIDOS” means “INVALIDS” in Spanish)
#NO VALIDOS: 000000
Wait, hold on a second, the number of invalid banknotes is being stored in a three byte counter in the EEPROM, starting at position 0xE. Are you thinking what I’m thinking? We should look for the opposite operation. Where is that counter being incremented? That path would hopefully lead us to the part of code where a banknote is considered valid or invalid 🙂 Keep calm and ‘EEPROM_write’
Bingo!
Function ‘sub_1FEB’ (I rename it ‘incrementInvalid’) is incrementing the INVALID counter. Now I look for where it is being called.
incrementInvalid‘ is part of a branch, guess what’s in the other part?
In the left side of the branch, a variable I renamed ‘note_Value’, is being compared against 5 (5€) 0xA (10€). On the other hand, the right side of the branch leads to ‘incrementInvalid‘. Mission accomplished! We found the piece of code where the final validation is performed.
Without entering into details, but digging a little bit further by checking where ‘note_Value’ is being referenced, I easily narrow down the scope of the validation to two complex functions. The first one assigns a value of either 1 or 2 to ‘note_Value’ :
The second function takes into account this value to assigns the final value. When ‘note_Value’ is equal to 1, the possible values for the banknotes are: 5,10, and 20. Otherwise the values should be 50, 100, 200, or 500. Why?
I need to learn about Euro banknotes, so I take a look at the “Trainer’s guide to the Eurobanknotes and coins” from the European Central Bank http://www.ecb.europa.eu/euro/pdf/material/Trainer_A4_EN_SPECIMEN.pdf
Curious, this classification makes what I see in the code actually make sense. Maybe, only maybe, the first function is detecting the hologram type, and the second function is processing the remaining security features and finally assigning the value. The documentation from the vendor states:
Well, what about those six analogue signals? By checking for the registers involved in ADC operations we are able to identify an interesting function that I rename ‘getAnalogToDigital
This function receives the input pin from the ADC conversion as a parameter. As expected, it is invoked to complete the conversion of six different pins; inside a timer. The remaining three digital signals with information about the distances can also be obtained easily.
There are a lot of routines we could continue reconstructing: password, menu, configurations, timers, hidden/debug functionalities, but that is outside of the scope of this post. I merely wanted to identify a very specific functionality.
The last step was to buy the physical device. I modified the original firmware to accept our home-made IOActive currency, and…what do you think happened? Did it work? Watch the video to find it out 😉
The impact is obvious. An attacker with temporary physical access to the device could install customized firmware and cause the device to accept counterfeit money. Taking into account the types of places where these devices are usually deployed (shops, mall, offices, etc.)  this scenario is more than feasible.
Once again we see that when it comes to static analysis, collecting information about the target is as important as reverse engineering its code. Without the knowledge gained by reading all of those documents and watching the videos, reverse engineering would have been way more difficult.
I hope you find this useful in some way. I would be pleased if this post encourages you to research further or helps vendors understand the importance of building security measures into these types of devices.
References:
 
[1]http://www.inves.es/secureuro?p_p_id=56_INSTANCE_6CsS&p_p_lifecycle=0&p_p_state=normal&p_p_mode=view&p_p_col_id=detalleserie&p_p_col_count=1&_56_INSTANCE_6CsS_groupId=18412&_56_INSTANCE_6CsS_articleId=254592&_56_INSTANCE_6CsS_tabSelected=3&templateId=TPL_Detalle_Producto
[2] http://www.secureuro.com/secureuro/ingles/menuingles.htm#
[3] http://www.secureuro.com/secureuro/ingles/MANUALINGLES2006.pdf

 

[4] http://www.youtube.com/user/EuroSecurytec
INSIGHTS | March 14, 2013

Credit Bureau Data Breaches

This week saw some considerable surprise over how easy it is to acquire personal credit report information.  On Tuesday Bloomberg News led with a story of how “Top Credit Agencies Say Hackers Stole Celebrity Reports”, and yesterday there were many follow-up stories examining the hack. In one story I spoke with Rob Westervelt over at CRN regarding the problems credit reporting agencies face when authenticating the person for which the credit information applies and the additional problems they face securing the data in general (you can read the article “Equifax, Other Credit Bureaus Acknowledge Data Breach”).

 

Many stories have focused on one of two areas – the celebrities, or the ease of acquiring credit reports – but I wanted to touch upon some of the problems credit monitoring agencies face in verifying who has access to the data and how that fits in to the bigger problem of Internet-based authentication and the prevalence of personal-enough information.
The repeated failure of Internet portals tasked with providing access to personal credit report information stems from the data they have available that can be used for authentication, and the legislated requirement to make the data available in the first place.
Credit monitoring agencies are required to make the data accessible to all the individuals they hold reports on, however access to the credit report information is achieved through a wide variety of free and subscription portals – most of which are not associated with the credit monitoring bureaus in the first place.
In order to provide access to a particular individual’s credit report, the user must answer a few questions about themselves via one such portal. These questions, by necessity, are restricted to the kinds of data held (and tracked) by the credit reporting agencies – based off information garnered from other financial institutions. This information includes name, date of birth (or age), social security number, account numbers, account balances, account addresses, financial institutes that manages the accounts, and past requests for access to credit report information. While it sounds like a lot of information, it’s actually not a very rich source for authentication purposes – especially when some of the most important information that can uniquely identify the individual is relatively easy to acquire through other external and Internet-based sources.
Time Magazine’s article “Hackers Now Aiming For Your Credit Reports” of a year ago describes many of these limitations and where some of this information can be acquired. In essence though, the data is easy to mine from social media sites and household tax records; and a little bruteforce guessing can overcome the hurdle of it not already being in the public domain.
The question then becomes “what can the credit monitoring agencies do to protect the privacy of credit reports?”  Some commentators have recommended that individuals should provide a copy of state-issued identification documents – such as a drivers license or passport.
The submission of such a scanned document poses new problems for the credit monitoring agencies. First of all, this probably isn’t automatable on a large scale and they’ll need trained staff to review each of these documents. Secondly, there are plenty of tools and websites that allow you to generate a fake ID within seconds – and spotting the fakes will be extremely difficult without tying the authentication process to an external government authentication system (e.g. checking to see if the drivers license or passport number is legitimate). Thirdly, do you want the credit reporting agencies holding even more personal information about you?
This entire problem is getting worse – not just for the credit monitoring agencies, but for all online services. Authentication – especially “first time” authentication – is difficult at the best of times, but if you’re trying to do this using only data an organization has collected and holds themselves, it’s neigh on impossible given current hacking techniques.
I hate to say it, but there’s a very strong (and growing) requirement for governments to play a larger role in identity management. Someone somewhere needs to act as a trusted Internet passport authority – with “trusted” being the critical piece. I’ve seen the arguments that have been made for Facebook, Google, etc. being that identity management platform, but I respectively disagree. These commercial services aren’t identity management platforms, they’re authentication gateways. What is needed is the cyber-equivalent of a government-issued passport, with all the checks and balances that entails.
Even that is not perfect, but it would certainly be better than the crumby vendor-specific authentication systems and password recovery processes that currently plague the Internet.
In the meantime, don’t be surprised if you find your credit report and other personal information splattered over the Internet as part of some juvenile doxing attack.
— Gunter Ollmann, CTO IOActive Inc.