The State of Mobile Banking (in the UK)

News recently broke that Tesco Bank's Android App refuses to run when Tor is also installed on the handset, presumably in the name of security.

So, out of morbid curiousity, I thought I'd take a quick look at just how effectively various banking apps were secured. Banks, after all, should be at the forefront of security (even if they often aren't)

To start with a disclaimer - personally, I think using banking services on any mobile device is a bad idea from the outset, and some of the results definitely support that idea. I've only taken a cursory look, and not made any attempt to dis-assemble any of the apps.


The Banks

I ran the same tests against apps from a number of UK banks

App  App Name Size
Barclays Barclays Mobile Banking 50.40MB
HSBC HSBC Mobile Banking 10.71MB
LLoyds LLoyds Bank Mobile Banking 14MB
Natwest Natwest 7.34MB
Santander  Santander Personal Banking 9.48MB
Tesco Tesco Bank Mobile 20.64MB

All were run on the same phone, which connected out via OpenVPN to allow me to make various changes without impacting on other users of the local network


Permissions Requested

Although it wasn't my primary or initial focus, the range of permissions requested by some of the apps concerned me, so here's a breakdown of permissions per App

App Bluetooth
Conn. Info
Calendar Camera Contacts Device &
App History
Device ID &
Call Info
Identity Location Phone Photos/
SMS Wifi Conn.
Other Total
Barclays X   X X X X X X X X       9
HSBC     X X   X X X X X   X X 9
LLoyds       X   X X X   X   X   6
Natwest       X   X   X   X   X   5
Santander    X   X   X   X X X X     7
Tesco           X X X   X   X   5

 Under "Other", HSBC requested Smartcard service, nfc transaction (requested twice) and draw over other apps


Connection Security - Summary

My main interest was seeing what, if any, measures each app took against an attacker on the local network in order to protect data whilst it's in flight. The summarised results can be seen below

App Domain(s) DNSSEC HPKP HSTS Verifies
KeyStore HTTPS
Barclays N N N ? ? ? ?
LLoyds  N N N Y App Y Y
Natwest N N Y App Y Y
N N Y Y Global N Y
Tesco N N N Y Global Y N

Note: Barclays has inconclusive results because it flat out refuses to run on a rooted phone and I didn't have an unrooted one to test with.


Test Methodology

Because not one of the domains in use uses DNSSEC, DNS poisoning is incredibly straight forward. On the assumption that all apps would be communicating on port 443, I overrode their relevant RR's to point them at a box under my control and configured two NGinx reverse proxy stanzas for each.

Two Packet captures were run throughout each test so that the app's behaviour could be observed

For the first test of each app, I generated a snake-oil, self signed SSL certificate for the relevant domain to check whether the App would accept an entirely untrusted certificate (none, thankfully, did)

For the second test, a certificate was generated and signed by a self-signed CA trusted on the Android device being used for testing - the aim being to identify whether the app used it's own trust store (or perhaps a HPKP like check of the presented certificate). As we can see above, not all apps passed this test.

In both cases, the app was manually operated on the device - attempting to log in an account (using a made up identifier)

Packet captures were examined for anything of interest, including, obviously whether the mitm capture had managed to scoop up the credentials


Example configurations


local-data: " A"


server {
	listen 443;

	root /var/www/empty;
	index index.php index.html index.htm;


	ssl                  on;
	ssl_certificate      /etc/pki/tls/certs/;
	ssl_certificate_key  /etc/pki/tls/private/;

	ssl_session_timeout  5m;
	ssl_prefer_server_ciphers On;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

	location / {
		proxy_set_header Host $host;

server {

	root /var/www/empty;
	index index.php index.html index.htm;


	location / {
		proxy_set_header Host $host;

Packet Captures

tcpdump -i tun0 -v -s0 -w barclays2.pcap host $VPNIP # capture all traffic from the device
tcpdump -v -i lo -s0 -w barclays1.pcap port 80 # Capture any traffic that traverses the reverse proxy



Barclays Barclays

The tests couldn't be performed against Barclay's apps because it refuses to load on a devie that has been rooted. In fact the main reason it's still been included in this result set is the mammoth size of the app (50.40MB) and the fairly wide range of permissions it requests.

Upon launch, the app performs a number of checks to see whether the device has been rooted (including attempting to execute su). Simply moving su out of the way, unfortunately, isn't enough to fool it's checks.

Strangely though, although it refuses to do anything on a rooted device, it doesn't prevent it from generating a DNS Query for the backend FQDN, it just never tries to connect.

From what little can be observed, it's no better than the other apps, the domain it uses certainly lacks some fairly simple security provisions.



HSBC is unique amongst the apps tested in that it also requests "Other" permissions at install time. Most seem reasonable enough for a financial app (Smartcard service, and NFC transaction), though for some reason they appear to have included "NFC Transaction" in the manifest twice

In common with the other apps tested, HSBC's app verifies the certificate presented to it. Unlike some of the other apps, it doesn't appear to rely on the device's keystore, instead (presumably) only trusting CA's packaged into the app itself. This is good.

Curiously, although it's used by other connections initiated by the app, connections to the backend don't utilise the Server Name Indication extension - so I had to configure my MiTM box to serve the HSBC certificate by default

Analytics used by the app appear to be provided by Webtrend


LLoyds LLoyds

LLoyd's app requests a reasonably innocuous list of permissions and seems to do a pretty good job of protecting in-flight data. Although, like every other domain tested, there's no protection in place against DNS poisoning, the app appears to validate certificates against CA's included in the App rather than relying on the device's keystore

In common with every other app tested, the app submits data to an analytics service - in this case


Natwest Natwest

Natwest's app requires you to provide a mobile number in order to receive a one-time activation code.

It verifies certificates against it's own key store, rather than relying on the device's store

The analytics service appears to be provided by demdex


Santander Santander

In truth, I nearly forgot about Santander, though I'm glad I didn't

As we saw in the Result Summary, Santander are the only bank to have deployed HTTP Strict-Transport-Security on their backend domain. Well done them

Unfortunately, theirs is also the only app which requests resources using plaintext HTTP on port 80, with requests going out to both and

Whilst no Javascript files are obtained on a cleartext connection, the app does retrieve at least one JPG, which opens the possibility that an on network attacker could inject malicious content to take advantage of something like stagefright.

There's a certain irony in being the only (tested) bank to have set up HSTS and then willingly fetching content in the clear from another of your domains that hasn't had HSTS configured. It's a potentially serious issue IMO

However, unfortunately, it gets worse

Unlike the other apps mentioned so far, the Santander app does not maintain it's own keystore for verification of certificates, instead relying on the devices key store. So a certificate issued by any CA the handset trusts can be used to MiTM it's connections (see below for more on why that matters).

As a result of the MiTM, we can see that the app uses SOAP to communicate with the back-end. Here's a login attempt

<soapenv:Envelope xmlns:i="" 
xmlns:soapenv=""><soapenv:Header />
<soapenv:Body><Authenticate facade="SUKMOVWSI">

Much like the HSBC app, connections to the back-end do not utilise SNI


Tesco Tesco

Tesco being the app that started this little jaunt into the world of banking security, should be expected to perform quite well. After all, they've apparently reached the point where they can spend some time focusing on what other apps are installed on the client device!

Unfortunately, it seems that they've actually spent too little time considering the risks of a network level attacker, having been outdone only by Santander

The app relies on the devices keystore when verifying certificates, so much like Santander can more trivially be mitm'd (see below for more on why that matters)

Although their app is one of the larger of those tested, this appears to be because most resources are built into the app. Communication with the backend is via a RESTful API. It's worth noting that whilst they don't appear to connect to third party analytics, request headers do include a lot of analytical information

GET /broker/api/users/ids/12345678910b HTTP/1.0
Connection: close
X-ClientAppVersion: 1.7.0
X-AvlHeight: 1920
X-DeviceID: qjSqzDU7lzdLTrRimuCIkWyi1GB+uQWpmZrkw3cUenYrM4JdHCRL37yjNVSvlMyh
X-Timezone: Greenwich Mean Time
X-Language: English
X-Jailbroken: N
X-FullWidth: 1080
X-Mac: 10:A5:B0:2A:2C:A0
X-OSName: Android
X-Credential: MobWord
X-AvlWidth: 1080
X-FullHeight: 1920
X-OSVersion: 4.4.2
X-DeviceType: GT-I9505
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; GT-I9505 Build/KOT49H)
Accept-Encoding: gzip

The App also makes connections to which appears to be a fraud prevention service. The DeviceID seen above is presumably generated by InAuth (I didn't MiTM them to check). Unfortunately, it seems checking a fingerprint of the presented certificate isn't included in the "mobile authentication" package that InAuth are providing to Tesco, an unfortunate omission all things considered.



Trust Sources Matter

I've noted against each app whether it maintains it's own key store (or at least appears to) or whether it relies on the CA certificates that the handset has stored.

Keeping in mind we're talking about our personal finances, there are a number of reasons why this distinction matters so much;

The average android device, by default, trusts a huge number of Certification Authorities (on versions greater than ICS go to Settings -> Security -> Trusted Credentials to see the list) including CAs such as "Hellenic Academic and Research Institutions Authority","Japanese Government", "Taiwan-CA" and various Turkish CAs.

Any one of these CA's (or an intermediate certificate that they've signed) can sign an SSL certificate and have it appear as trusted by your phone's browser. Having a large list of CA's is fairly essential for a browser which might access services anywhere on the globe.

Apps, however, are somewhat different in that they tend to be single purpose. Your banking app will only ever connect to the bank's back end services (analytics aside). The banks know who they have their certificates signed by, and there's no reason to expect that a certificate issued to a UK bank is likely to be signed by "Japan Certification Services Inc".

The problem being, if the app relies on the device's key store, such a certificate will be gladly accepted. If, on the other hand, the App includes a small collection of trusted CA's that the bank knows it has it's certificates signed by (as well as some fallbacks), that Japanese signed certificate won't be accepted unless the bank uses that CA (or an intermediary signed by them).

Breaches of certificate authorities are rare, but do and have happened in the past. None of the domains the apps use are configured with DNSSEC, so the certificate being presented is the only authenticator of the service being connected to.


Additional CAs

Using the device's trust store continues to be a risk though, even if we assume that no publicly trusted CA will ever make a mistake or suffer a breach again in the future.

Sometimes a "trusted" CA on a device isn't one that's publicly trusted. Instead, it's a self-signed Certification Authority. Businesses commonly use these - if you've used your device at work, you may for example have needed to install their CA certificate in order to connect to the Wifi. 

Now, we're no longer looking at the security of a professional Certification Authority, but of whichever sysadmin is responsible for maintaining the CA in your workplace. A breach of that CA would be sufficient to allow an attacker to MiTM the Santander or Tesco bank apps for an entire company.

Various nastinesses have occurred in the way Android handles certificates in the past, so it's not beyond the bounds of possibility that at some point it might be possible for an attacker to push a "trusted" CA onto a device. For a browser, this would be severe, for a banking app it'd be critical.



Aside from an app managing it's own keystore, there are a number of fairly simple protections which could (but haven't) be put in place. Most would offer benefits to browser users too.

The first is DNSSEC. It's neither particularly new or difficult to set up - it works by cryptographically signing resource records to make DNS poisoning more difficult. Had any of the banks configured their domains to use DNSSEC, I'd have had a harder time directing bank-bound traffic to my box (though far from impossible). Most, if not all, of the banks use CDNs but CDN's have had support for DNSSEC for quite some time too.

Key Pinning (HPKP) should also be in use. Having the app maintain a limited keystore mitigates this a little, but key pinning can be as simple as adding a single HTTP header. Both Android and iOS support it, so why isn't it in use?

DNS Based Authentication of Named Entities (DANE) is similar, in effect, to HPKP in that it allows a domain owner to specify which CA can issue certificates for a given resource. It does require that DNSSEC be in place, but other than that is - again - simple to configure.

Connections should be HTTPS By Default. Santander uses cleartext connections to fetch various resources, providing a vector to launch a side-channel attack against the HTTPS protected content.



I've never been overly inclined to trust my financial security to a mobile app in the first place, but it seems that an industry that (you'd hope) should be leading the way in terms of security is lagging badly behind in terms of implementing basic protections.

We'd consider it bad if a website handling payments were subject to a MiTM, but what happens when it's a service that allows access to your finances in their entirety?

More concerningly though, whilst the subject of this little distraction was Apps, the banks listed generally lack protections on their websites too. So if you ever access Internet Banking from work, you may want to give some thought to whether or not your employer has a CA installed on your machine.

For their part, most of the apps tested were relatively robust, at least against the fairly basic attacks I ran. Two of those apps, though, performed very poorly, in a manner that's entirely avoidable (and would be avoided if the various protections available were in place). But it should also be noted that this was not a sophisticated attack - in fact it was pretty much as simple as a MiTM can be. With a little more effort, and inspection of the apps themselves, it's likely that even the more robust of the apps might fall prey.

Santander's use of HTTP to retrieve various resources is, in my opinion, an unmitigated disaster. The issues with use of the global keystore are mitigated by the fact that an attacker would need to compromise a CA your device trusts (or find a way to insert one). In contrast however, Santander's use of HTTP to retrieve images means that an attacker could feasibly use Stagefright, a vulnerability that's believed to still impact millions of devices.