Showing posts with label security. Show all posts
Showing posts with label security. Show all posts

Friday, November 25, 2016

Native apps can't be trusted

The one thing the web has gotten right to some extent (thanks to the beauty of REST/HTTP) at least compared to desktop and native apps, is how it can uniformly show users if they are using a secure connection to a trusted source. The browser does this by clearly and consistently giving various hints (see Fig 1 and Fig 2 below):

Fig 1. Firefox indicating that you are securely connected to GitHub.

Fig 2. Chrome indicating that you are securely connected to GitHub.

There is no reliable, trustworthy and consistent way for non-technical users to do this on desktop and native apps.

This is how you add funds to your Paytm wallet from within the Uber app (see Fig 3 below):

Fig 3. Page to add funds to your Paytm wallet from within the Uber app.


Notice the following in Fig 3:
  1. Since I opened this from within the Uber app and this "page" is running "inside" the Uber app, I have no way to verify if what I'm seeing is in fact a page severed by Paytm or a spoofed page that Uber is presenting to me.
  2. Even if I were to trust Uber here, there is no way for me to tell if this is happening over a secure connection.
  3. Say I'm willing to accept that this is in fact a page served securely by Paytm, I have no way to know if Uber has injected their own code to intercept everything I enter on that page.
  4. And now the really ridiculous bits (circled in red in Fig 3 above): The text that reads "Your payment details are secured via 128 Bit encryption by Verisign" and the various logos that are displayed at the bottom of the page are something I have to take at face value. These are also app-specific and not consistent.
Also, note that I (as a non-technical end-user) have no way of knowing if all communication the Uber app is doing with it's servers is over a secure channel. I just have to "trust" that they are doing the right thing. Of course, as a technical user I could intercept the traffic on my phone and see how it's been sent, but that is exactly the point: You have to jump through a lot of hoops to "verify" what is happening.   

The current state of affairs for security on native apps is absolutely ridiculous and it's crazy that we all put up with it.

Full Disclosure: I work at Zeta (at the time of writing this blog post), but the views expressed here are my own and not of my employer.

What native apps get wrong over web apps

  1. They need to be installed. This in itself is a big drawback.
  2. They need to be separately developed for each target platform. Unlike the desktop app days where Windows was almost ubiquitous, with mobile you have to support 2 platforms.
  3. They can get outdated if users don't upgrade. We are doomed to repeat the same mistakes we made with desktop apps.
  4. Deployment is blocked on a black box not in your control (aka the app store approval process). Kiss continuous deployment goodbye.
  5. They have no trustworthy way to indicate to users that secure channels are being used to communicate secure information (unlike the address bar in web apps that clearly shows if the connection is secure and to the right place). If you think about it, there is a beauty to REST/HTTP that makes this possible.
  6. Each app needs to reinvent the wheel and ship infra that could have been shared, e.g., local data store, caching, etc.

Monday, April 25, 2011

Secure (transient) storage of passwords for external APIs that don't support OAuth

My latest project, OboxApps.com, a mobile app suite for LogicBoxes (LB) and Resellerclub (RClub) users, has to deal with the the awkward situation of storing the users credentials to make API calls on their behalf.

Searching turned up some great answers by ircmaxell on how to deal with situations like this:
  1. PHP 2-way encryption: I need to store passwords that can be retrieved
  2. Encoding cookies so they cannot be spoofed or read etc

For increased security, I wanted the storage to be transient (duration of the session) and did not want to store the password on the server. So this is what I came up with:
  • I ask the user for the API credentials over HTTPS.
  • Verify that the creds works by making an API call.
  • Generate a 128 character random salt.
  • Encrypt the password using the random salt with the method used in the Encryption class from answer 1 above.
  • Store the random salt and API username in the session.
  • Send the encrypted password to the client in a secure (HTTPS), httponly cookie.
The API credentials and the encrypted password cookie are transmitted over HTTPS to protect against any kind of sniffing and the httponly property of the encrypted password cookie ensures that client side JavaScript cannot access it through XSS attacks (although it is not supported by all browsers).

Additionally (as suggested by ircmaxell in a private conversation), I could also look at implementing the Secure Cookie Protocol (pdf) for the encrypted password cookie and ensure the salt is sufficiently strong by using a derivation function such as KDF3 on the random salt to prevent or at least curb brute force attacks against the key generator, but I think this is good enough for now.