Possible App Impersonation Attack


#1

Let’s say there is a mobile app called Authentic App that uses Blockstack sign in and stores data in Gaia buckets for its users.

Currently, Blockstack authentication on mobile is handled through a publicly accessible redirect endpoint on the web for the app. Let’s call is redirect.html. To make this work, the mobile app has a custom protocol handler that is unique to the app. On iOS, this is done through adding URL types on the app’s Info Page which involves specifying unique Identifier and URL Schemes . This make it possible for the app’s web-based authentication redirect.html endpoint to redirect the user back to the mobile app.

Let’s assume that redirect.html for Authentic App is hosted at www.authentic.com/redirect.html

This means that anyone who knows the strings used as Identifier and URL Schemes on the mobile app can create an app, let’s call it Fake, where users can login and use the Gaia buckets for the app www.authentic.com, thereby impersonating Authentic App. Fake can then decrypt any useful files that the users might have encrypted while using the authentic app, or can delete any useful information that the user will have created using the authentic app.

One could argue that we can randomize the name of the redirect endpoint to something like www.authentic.com/vErYRaNdOmAnDlOnGnAMe.html using a random string generator of some sort, and then make it harder for an adversary to know the name or the URL string. I don’t think this will work since the adversary can figure out the name using the URLs of traffic going in and out of the app during Blockstack Authentication.

Another line of defense we have is that the Identifier and URL Schemes are part of the compiled code given to users of the app and hence it is harder for anyone to know them. I am not sure how true that is since I am novice to this. However, I believe that a highly motivated and financed adversary has good enough tools, time and other resources to “de-compile” the code and get attributes like Identifier and URL Schemes since these are names used to identify the app in the phone, hence they should be somewhere accessible. Also, the URL Schemes is also hardcoded on www.authentic.com/redirect.html which is a publicly accessible file.

Given the nature of the applications being built on Blockstack, and Afari in particular, it makes sense to believe that we will have enough targets on our back for people trying to “break” the application.

I can’t think of ways to fix this — let me know what you guys think. I have also opened an issue on the iOS repo to make sure that we do not forget about it.

I know that all of this is work in progress as per recent post by @larry and there is a similar issue (and possible fixes although I am not really sure) by @MichaelFedora.


Do You Own Your Data If You Can't Control Or Access It?
2018-10-10 Engineering Meeting
Authentication Changes Should Not Break Existing Applications
#2

I think that is a better layed out case study than what I put in the comment you linked, but it is similar to the issue I was describing.

I don’t know enough about how mobile applications work in regards to URL schemas and such, but from what you wrote it definitely seems to be an issue if Blockstack wants to grow on the mobile and other native platforms.

I think the solution to this would be using the name systems for apps.You could store a public key in the app’s name’s zonefile, and auth responses would be sent back to the app encoded with that public key, requiring the private key to decrypt and then get the Gaia Storage Hub key. Or, to skip a step, simply use the app’s public key (within the name’s zonefile) to encrypt the files to be used by that app… could introduce some other possibilities such as inbox messages only openable by that app, etc.

To summarize:

Use the Name system for apps (authorized.app), and store their public key within that name’s zonefile. Only the app will have the private key, no-one can pretend to be the app and open up the data, and if the private key is lost from the app developer then all the data will become void.


#3

I agree. I’d love to extend the authentication protocol so app assets could be signed by the owner of a Blockstack name. Ideally, the Blockstack name would do the following:

  • Vouch for the redirect endpoint – specifically, the zone file should contain the hash of the redirect.html file, and the app should validate the redirect.html file against the hash.
  • Vouch for the manifest.json file, and have the authenticator (1) validate the manifest.json file against the hash, and (2) show the app’s Blockstack name to the user on the “Sign in” screen (e.g. “This app – afari.io – is published by felix.id” or something).
  • Serve as the input for the Gaia bucket private key derivation (right now, the app’s Origin string is used for this). Then, the app URL can change without breaking user buckets.

#4

Both iOS and Android provide more secure methods of redirecting to apps. Universal links in iOS and App links in Android. They both require an association file to be available on your website that links the site domain with your app identifier. The OS will only handle redirects to the app with the exact matching bundle identifier. (Bundle identifiers are unique and cannot be spoofed)

In the iOS case, you should already might be able to do this by uploading an app site association file that handles the redirect URI path.


#5

In Android it works already with App Links. You only have to follow the wizard in Android Studio for App links
The Manifest looks something like this: https://github.com/blockstack/blockstack-android/commit/756e0e3c711c3c06be58bf9f39a9aca605104bfe

The corresponding issue for Android is #7, requiring to update our documentation.


#6
  • Vouch for the redirect endpoint (hash)

Given the fact that start_url already exists within the manifest.json, how necessary is this? What if my redirect.html is simply part of a SPA web app and thus would need to be updated every time I update the app? It doesn’t help to authenticate the entire app because you could use a redirect.html page which, while hashed, simply redirects to another page to bypass the check, therefore only accomplishing the same amount of verification as the start_url within the manifest.json hash…

  • Vouch for the manifest.json file (hash & app/author name)

I like this, and while it means another transaction every time you need to update the zonefile, it seems necessary for security reasons. The latter part of the vouching reminds me the web app manifest, though I also know most of the manifest info is within the manifest.json. I wonder if there are any fields that should be in the zonefile versus the manifest.json? Perhaps the former could have default fields that the latter would override… I don’t know, seems like it could be interesting though.

  • Be used as private key seed

I don’t like this still. If a name runs out and isn’t renewed in time, then someone else can steal the data, in the same way where an attacker can acquire the DNS domain if it isn’t renewed in time. Is there an issue that I don’t understand when it comes to developers deciding what their public/private keys are? (I’m a little persistent with this in order to solve this issue)


#7

The authentication protocol would need to deny HTTP redirects when fetching the redirect.html file. But as Ken pointed out, it sounds like universal links would address a large amount of this problem.

I’m not sure I understand the former concerns. My understanding of the redirect.html file was that it’s just a way to bounce users to the hosted browser. Admittedly I don’t work on the mobile SDK, so I’m probably missing some subtleties.

We’d likely create a namespace like .app or something where names don’t ever expire. App developers could also publish under a subdomain – subdomains never expire, so this would be safe. Either approach would also solve the issue you linked about Gaia buckets not having a stable derivation path due to their dependence on DNS names.


#8

Good thoughts here. I think we’ll have to implement an approach for encrypting the payload that’s sent back to the app. OAuth works such that you need to use a server-side access token to fetch the actual payload. This is similar to using an app’s “public key” to encrypt the payload, however we do that.

At some point we’ll want to provide the ability for users to request data under a different app-specific Gaia hub than the app you’re using. This is key for data portability. Say, for example, that there is a photo-sharing app, “photostack.com”. Then another app gets built, and you want to use your same photos with that new app, call it “stackphotos.com”. The user should be able to request their “photostack” data and private key to be shared with “stackphotos”. In this case, the most important thing is to provide transparency into the authentication flow.

In the latter case, we’ll probably want to implement a new kind of auth flow for getting data from one app and using it in another. We could have a very clear auth grant modal that says “StacksPhotos is asking to receive your data from PhotoStack”. Then, the payload could be encrypted with the StacksPhotos public key.

I’m getting ahead of myself here. I think we’re mostly on the same page around encrypting the payload with an app’s public key.


#9

The “impersonation attack” description sounds like a user choosing to access their data from a different dApp (i.e. using TweetDeck to access Twitter data). The user downloads Fake.app knowing that it is not Authentic.app. @Jude’s point about clearer messaging to the user when accessing Authentic.app’s bucket from Fake.app is important.

Here’s an illustration of the situation today when a Stealthy User taps to access their Graphite bucket (using redirect.html):

It could be clearer if it said something like @hank suggests or this: “Would you like to access your Graphite data from Stealthy? (Tap to learn more.)”

@felix, did I miss something in your post where Fake.app is concealing from the user that they are accessing Authentic.app’s data?


#10

@hank, you bring up some really important points that would go a long way towards showing users that they not only own their own data, but can control it too.


#11

Just an update for Android: There is a PR that describes what developers need to do to use app links (https://github.com/blockstack/blockstack-android/pull/98)