How I stole data from user accounts on Google

You don't know me, but there is a certain possibility that I do know you. The reason is that I have full, unlimited access to the private information of millions of people hosted on Google accounts. Bank statements sent by mail, medical documents stored on Google Drive, saved and forwarded chats from Facebook, voice messages on Google Voice, personal photos on Google Photos. The list goes on. None of them know about it now and will never know in the future. Perhaps you are one of them.



How did I do this? It all started with an application I developed. For obvious reasons, I will not publish the name. The application is quite simple, it is designed for people who are fond of fitness, and offers options such as entering data on speed during a run or ready-made strength training complexes. Like many other products, it requires the user to create an account first. According to analysts, about 60% of people, instead of going through the entire registration process, are tempted by the tempting "Sign in with Google" button.





You probably know in general terms what happens in such cases: when the user clicks on a button, a browser window for logging into a Google account opens inside the application.





This user has two-factor identification enabled, so after he has entered the mail and password, a dialog box pops up asking if it is he. The location and device type are the same, so he clicks on "Yes".





That, in fact, is all. Now a person can safely use the application, while I, meanwhile, get full, unlimited access to his account from a remote server. He will never receive any messages about this. And if he turns out to be meticulous and begins to study network traffic, he will see that the device sent network requests only and exclusively to various subdomains of google.com.



But how is this even possible? Let's go back to our "Sign in with Google" button. Let's make one thing clear right away: for those who are not in the know, after clicking this button, the application can do anything. Launch the authorization process in Google, give a trumpet voice, show a gif with a cat. Not all options from this list are equally likely, but you can dream.



In my case, by clicking on the button, the application opens a dialog box using the WebView and sets the web address: accounts.google.com/EmbeddedSetup . It does correspond to the Google account login page, only a special one designed for new Android devices. This circumstance will play its role later, when we are kindly provided with all the necessary information in the form of a cookie.



Unfortunately, this page both looks and acts differently than the standard login page (at least the way it should be by default):





Notice the strange blue stripe, the words Learn more and so on in the right picture.



And now the fun begins. I use the standard APIs built into both iOS and Android to inject a well-written piece of Javascript code that will make the necessary modifications so that the page does not differ from the standard one in terms of its appearance or behavior.



The shrewd ones will now think: "Stop, so if you can inject JavaScript code, what prevents you from simply stealing your login and password directly from the text fields?" Absolutely nothing - generally speaking, there is already a ready-made code for this purpose exist. But nowadays, access to login and password is no longer enough. Unless you are very lucky, the server will be within a few hundred miles of the user's location. Otherwise, the user will receive a letter and notification with a message about "suspicious activity" and the hacking attempt will be stopped. And two-factor authentication makes our life even more difficult.



So let's talk about something else, like the master token. At first glance, it looks somehow unkind, but at the second - it turns out to be even worse than it seemed.



When the Android device first logs in, it sends the token received from the aforementioned built-in login page to a special endpoint. Here's an example of a typical request:



POST /auth HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 349
Host: android.clients.google.com
Connection: Keep-Alive
User-Agent: GoogleLoginService/1.3 (a10 JZO54K);gzip
app: com.google.android.gmsapp=com.google.android.gms&client_sig=38918a453d07199354f8b19af05ec6562ced5788&callerPkg=com.google.android.gms&callerSig=38918a453d07199354f8b19af05ec6562ced5788&service=ac2dm&Token=oauth2_4%2F4AY0e-l5vPImYAf8XsnlrdshQQeNir3rSBx5uJ2oO9Tfl17LpsaBpGf1E2euc18UyOc8MnM&ACCESS_TOKEN=1&add_account=1&get_accountid=1&google_play_services_version=204713000
      
      





The token in this request is taken from the cookies of the account login page, and everything else is information that is publicly available (thanks, microG !). The same account login page handles things with two-factor authentication - we don't have to do anything at all.



After that, the aforementioned endpoint sends the same master token. But how would I get access to it without suspicious network requests? Very simple: via a log in Google Firebase.



And the master token is powerful. It has an unlimited period of validity, provided that the user does not change the password or two-factor authentication settings. As far as I know, it is not subject to any security checks, regardless of location, IP and actions. It never provokes the system to send a notification or letter to the user.



And most importantly: it opens the way for me to all, without exception, services that have ever been available from a mobile device, on behalf of the owner of the corresponding account. One POST request is enough for me to pretend to be an official Google account and get an OAuth token to access anything, including private (and most likely not published anywhere) APIs. I can read emails, browse Google Drive, view backups from my phone and photos on Google Photos, and at the same time read the user's web history and chat with his friends on Google Messenger. I even created a modified version of microG with which I can manage all of these user accounts directly from regular Google apps.



And I remind you, the whole process looks like this... I invite everyone to ask the question: would you get caught?



Exposure



As many of you have guessed, not everything in this article is true. I have not published any fitness apps on the Play Store and have not collected millions of Master Tokens. Thanks to this post for the inspiration. But the method itself works. I, and any other developer, could definitely make an application with such a surprise (maybe someone already did).



FAQ



But the page is different from the normal login. I would have noticed!



The differences are not so striking, so most likely they would not have noticed. The Google account sign-in page on Android usually has a "select an account" interface, but there are exceptions - for example, many web applications, such as those that are made on Ionic and Cordova. Most iOS applications also often prefer the web version, which is very similar to the above option. In addition, even if it seems to you that the absence of a screen with "such and such an application is asking for access ...", you will definitely be alerted, then it may well be implemented at the cost of several extra hours of work.



Does this work on iOS too?



I haven't tried it, but there is no reason to believe that it won't work.



And what to do with it?



In general, the question is complex. None of my actions, strictly speaking, fall under the definition of an exploit, but the result is nevertheless very dangerous. For starters, Google would like to sort out its "sign in with a new device" notifications so that they work fine. Personally, I get them when I try to log into my account from a computer, but while I tested this application, the system never worked. Another good idea is to update the guidelines for the "Sign in with Google" buttons; now it doesn't say anything about implementation requirements at all. Perhaps they should delve deeper into the security jungle through obscurity - a principle, for all its flaws, so far serves Apple well for iMessage security.



I have to admit: I am not sure that a technical solution can be found here that would completely eliminate the problem. If the official Google application has the ability to perform some action, then third-party programs, with due diligence, will be able to repeat it. However, the company employs smart people, so wait and see.



Is this problem relevant for all authorization systems in third-party applications?



Quite possibly. I did not understand thoroughly in which cases notifications were sent and in which they were not, but even when notifications arrive, it is not always clear from them what is happening. The "Sign in with Apple" function, however, is equipped with a very strict guidelines, and the App Store administration (where the function, I believe, is mainly used) strictly monitors compliance with the requirements. On the other hand, they have their own problems with authorization, against which this fades.



Real story



Even if it was not millions, I somehow really collected a small amount of master tokens from unsuspecting users, and quite unintentionally.



The real story of my epiphany began when I developed the Carbon Player application; now it has already sunk into oblivion, and has not received widespread distribution. The app was conceived as a replacement for Google Play Music (remember the days when that existed?), Only with a much cooler design. To access the custom music folder, I translated gmusicapiSimon Weber in Java, but, while rewriting the code, at first I did not really understand how the authorization process works there. I only realized that I needed a username and password, which I requested through a simple dialog box, and then some requests come and some tokens that are suitable for me to extract music fall out.





Before transferring the first version of the application to a small group of testers, I combed through the code, added logging everywhere and also implemented an interceptor, which was supposed to automatically upload all logs to Firebase. Of course, I was smart enough not to log passwords, but I pledged the three tokens received by my gmusicapi implementation by mistake. Two of them were pretty harmless - they only gave access to different music stores. But the third turned out to be a master token.



In general, the application has collected at most twenty-five downloads during its entire existence, and I quickly waved my hand at it so as not to be distracted from my studies. But before that, I managed to release a couple of updates, one of which was a redesign of the new awesome (well, at that time) Google Play Music home page - one of the few elements of the original product that looked good.





The process turned out to be much more confusing than I thought, and unexpectedly had to do a lot of reverse engineering of Protocol Buffers. More importantly, for some reason, it now required a completely different token, which was no longer implemented in gmusicapi. As a result, in order to implement it, I dug into the authorization system for several hours, trying to figure out how it works. This led to a terrible moment of epiphany when I realized that I was logging the most sensitive information I could. I will say one thing: the logging has stopped. Twenty-five people who downloaded the application, forgive me, please (I deleted your tokens from Firebase!).



There was another, unrelated to the first time when I worked at a startup creating a password manager. One of the key advantages of the application was that it stored passwords strictly on the phone, but at the same time allowed authorization from the computer thanks to a JavaScript bookmarklet that “connected devices” via a QR code. To make everything go smoothly, when a user opened a site on a computer, the application accessed the same site from the phone and injected a carefully written piece of JavaScript code that captured logins, passwords, and everything else. Sound familiar?



In the end, these two ideas came together in my head. I had a prototype for Carbon Player but didn't have enough time to get it to work. A few years later, I finally started to create something like a demo version on its basis. A lot had to be changed in the process - the method described in this article is significantly different from what was implemented in the prototype, since Google made changes to the authorization system. But the end result remains the same and is no less frightening than it was then.



If you want, you can download the demo versionand see the system in action; I give my word that nothing is logged to the cloud. Keep in mind that the application is very simple and has hardly been tested, so there is a good chance the method will not work if your account has a different configuration. Thanks for reading the article, I hope you enjoyed a little reminder of the importance of questioning everything. Even the most harmless things sometimes hide something not very pleasant inside (although in the case of ice cream cake it happens the other way around).



All Articles