Saturday, May 20, 2017

How do you fix mobile banking in Canada? Part 1

Warning - this is technical post for mobile programmers.  
It may also get sweary or ranty.

This is a post that has been brewing for a long time. Depending on the reaction to this post, it may become part of a series. I've got a spleen-full that needs to be vented on this subject. I'm going to try kicking off a conversation that many people think just doesn't need to happen, but I really think is long overdue. It's going to get technical, because that's where my gripe is and where the possible solutions lay.

So here goes...

Contrary to the slick marketing and web pages on various bank websites telling gullible people that things are really safe, digital banking is minefield full of scammers, bad programmers, incompetent security people, dodgy delivery platforms and that's before we get to the customer, their choice of wifi access points, etc. 

I bank with CIBC and Scotiabank and don't allow either bank to have apps on my mobile phones.  I've worked with many banks over time (first in Canada would be RBC in 2000, as I was on the Palm Pilot Banking app, last in Canada was TD in 2015, working on iOS).  I don't give my wife any stick over her decision to use the TD app on her iPhone because I've personally seen that code, worked on it, seen other people who worked on it, seen how it's built, sat in the QA team talking to the people actually testing it, their cybersecurity people have bought me beers, and I have a good ongoing relationship with everyone. I feel it's reasonably secure as long as she is equally careful with her phone.  However, both my wife and I have a Scotiabank account, and the Scotiabank app is banned in the house, just like the CIBC apps were banned in the house years ago. 

You're probably wondering why I'd be so against Canadian banking apps? It's down to two reasons:
  • The evidence usually shows me that I cannot trust the banks.
  • My view is the apps the banks put out are clearly in contradiction to the marketing message about safety.
Just to back up what I'm talking about with trust, you may remember Scotiabank had a problem with unauthorized code making it public where they had over a million people walking around with "Fuck kony" (sic) in their pockets.  It's not just Scotiabank either. My other bank, CIBC, has for years been feeding me a line, telling me that as a customer I'm appreciated, whilst simultaneously having this nugget in their ember.js system where the English translation for "idiot" is the French for "you" ("toi")...

 
Example of a CIBC insult in a customer facing system, 
where "idiot" in English is "toi" (you) in French.

Both of these unauthorized additions prove that basic crap slips past the same people who are supposed to be looking out for this stuff. Whether that's laziness or carelessness, these things do happen and this all eroded my trust a long time ago. 

I mean seriously, ask yourself if you would you use a system where the programmers evidently have contempt for the customer?

Now onto the second point above...  The public is told things are all nice and secure, but in an age where crap design or lazy programming puts millions of people at risk very quickly, I find myself shaking my head in disbelief on a regular basis. 

One example (and this is where this could turn into a series because theres a lot of this crap going on) is security around URLs in apps.  Basically, there's none.  Nobody ever thinks to bury that shit somewhere safe, and so API endpoints and hosts for banks are thrown around like confetti at a wedding.  It's a totally nuts situation when you think about it.

To back up what I'm talking about, here's code from a very well known payment wallet system in Canada that is live right now. Any script kiddie can upload the APK to an online decompiler, or shove it through a ClassyShark string dump and get every endpoint to start poking about.   


(Click image for embiggend version)

Really.... what the hell is with the suspicious non-secure IP address pointing at India? Did they hire an Indian outsourcing company to write this wallet and now it's phoning home to the mothership?

 
(Click image for embiggend version)

If you're wondering why that Android wallet app has strings just sitting around in a class where they can be read, this is STANDARD PRACTICE in Canadian Android banking apps as nobody ever designs it to be secure, or puts any effort into trying to hide things like URLs.  

No, really...  "Industry Standard" or "Bank Grade" security in mobile apps in Canada is like this... If all banks have the same non-security, your bank can also do nothing security-wise and then claim in your $5m advertising campaign that your app is secured to an "industry standard".

That's not security. That's theatre. 

Another example of this stupidity is from this past week, when Scotiabank pushed out another Android banking app (v17.4.0). I've been harping on about this particular app for over a year. My personal opinion is it's downright dangerous.

 
(Click image for embiggend version)

As you can see in the above image, even though as programmers they should know Java is insecure, they are still just dumping everything in a simple class as fully assembled strings.  There's so much wrong-ness here, I don't know where to start.  It could be the lack of obfuscation, or the fact the strings are stored in their entirety, so you can simply string dump the app to get the URLS. I'm not even getting into bank server side security in this article.

My brain can't comprehend why a) anyone approves of this type of dangerous code, or b) why security people in the bank aren't thumping the team that puts this out over the head with Android tablets.  However, as you can see, Scotiabank is doing nothing different security-wise to what the payment wallet system is doing.   

Now, this app has another security problem, which the CIBC payment app that got pulled in April used to have as well; they use the Enstream framework that communicates with Bell Canada over http, not https.  Yes, the same Bell Canada that just leaked 1.9million customers info.  

Now, I can point at other banks (and even into Bell Canada) and you'll frequently run across the same bad practices.  In fact, many programmers and managers just bounce from bank to bank spreading their bad practices and picking up new bad habits - which introduces a kind of predictability over time.  

So now I'll go back to the question in the title - how do you fix mobile banking in Canada?

Well, the first problem is communicating with them about problems. When I started looking at the mobile problem and tried communicating with banks, I found there was a minority who would entertain listening to me, and the majority would talk to me like "We're a bank, we know what we're doing. We don't need to listen to you".  Contrary to the usual cool Canadian reaction, I've had American's stick a guy on a plane immediately and that night I'm in their hotel bar in Toronto explaining what I see.  Same thing with the British authorities after the Tesco bank hack - the British also had open arms and were ready to discuss stuff.  Whilst CIBC has partially changed their tune with me (no longer do things just go into a black hole, they now listen), we don't talk until we really have to, because it's a shaky customer relationship (see "idiot" thing above for example). 

At one end of the spectrum I can openly communicate with a bank like TD, or the Loblaw people at PC Financial, and at the other end of the spectrum is Scotiabank, where they told me in December their VP of Security was looking for my phone number to urgently discuss a code leak and it's now May.  When customer service is just fobbing people off with platitudes and lies, there's obviously a snowballs chance in hell of a conversation .

The next problem is trying to work out how this type of problem keeps coming up?  Like why would Scotiabank for instance keep screwing up security this badly?  It's obviously not money because they're a bank in Canada.  It's not time, as they've had like 10 years to fix this. 

The only reasonable conclusion I can arrive at is they are clueless, and don't know what they're doing.  

Now, I believe that if you're not part of the solution, you have to have a good hard think about what you are.  To that end, I'm now going to explain to every Canadian bank that repeatedly puts out Android apps with URLs on full display, what I mean when I say "Bury that shit in C/C++".


The following is a lesson where I show you how to put your server address somewhere not on full display to every 12 year old script kiddie.



Step 1.  Create your project.


Create a project with the correct app name.  Check the "Include C++ support" box.



Specify your platform.


Leave C++ Support at toolchain default.




Step 2 - Customise the app to your needs

Rename the default cpp file to "security-lib.cpp"



Note that after renaming the file, it will disappear. This is normal.



















Open the CMakeLists.txt file. 


Change Line 14



Change Line 20
 


Change Line 40


Refresh your cpp projects.


Now your security-lib.cpp file shows up properly.



Step 3 - Customise your C++ file.

First create a class called ScotiaNativeBridge.  You need this because native sandboxing will force you to create a new C++ method for every class that accesses it - so we'll make every Android activity call this class, giving a single entry point.


Throw some code in it.


Important:  Look at the package name.  Look at the class name.  Shoving it all together, you have:
com.scotiabank.banking.ScotiaNativeBridge
...remember that.  It comes up in the next step.

Throw code in the cpp file.


Take that really long name I said to take a note of, prefix it with "Java" and suffix it with a function name.  That is part of the security that makes sure only your ScotiaNativeBridge class can access this.  The function is on line 9 of that ScotiaNativeBridge class. 

Now, look at the C code above.  The entire URL string doesn't exist in code.  We have decoy values too.  Depending on which build we're in, we're assembling the right components at the time we need them - which is the only time it exists.  

This means if a hacker looks in the compiled C code, they're faced with the following barrage of real and dummy values... That will remove more of the amateur hackers a bit more as you're not handing the values over on a plate.  

They now have to work for it.



Finally, go to the main activity of your app.  Throw this code in - it shouldn't need explaining.



Now run it.  The first time you do this, you may get this box - just hit Yes.



So, do we get the correct server URL if we compile in production mode?  Yes, we do.



End of lesson one...




So, there you go.  In Canada things have gotten so ludicrous it means that their customers now need to show the banks (for free) what the damn solution is to the Android problems they pretend don't exist.  

Given I know all of Canada's major banks now read this blog, there's now no reason for anyone to push a single Android app with exposed URLs to millions of customers.  Though personally, it's my view that any Canadian bank that makes $2bn a quarter in profits and has had nearly a decade to address this problem has no excuse anyway to continue foisting insecure crap on the public. 

I'll wait to see what the reaction is to this blog post, before tackling some of the bigger stuff on the pile like obfuscation or stopping code leaks.