Five years ago, at 17, while working on my app, I found a strange request while debugging the app via Charles Proxy – HTTP debugger.
I had no idea why my app made this request, but it was definitely interesting: the id in the response looked like a Google Ads Unit ID. It turned out that some part of my application was sending requests to an unknown server and received identifiers that were used to determine who got the money for showing ads.
What made this request
After some research, I found where the request came from. It was the Cordova Admob Pro plugin, which I used to show Google ads.
To be honest, it was the first time I actually read this section on GitHub. I had no idea that I was giving away the 2%.
This explained why I was getting requests with Ads Unit ID in it, so I calmed down for a while. But I was still curious about the “r” property in the JSON response. My working hypothesis was that it was the percentage that I shared with the plugin’s creator. To check it, I changed the app id property in the API request to a random one and got “r” equal to zero.
I felt like I was robbed, and this was exactly what happened.
Getting my money back
I wrote an email to the owner of the plugin.
His reply was met with some mixed feelings on my side:
1. The wow part was that it seemed like he was going to return the money. I honestly hadn’t expected any answer whatsoever.
2. The explanation for the “higher rate” was weird 🚩🚩🚩🚩🚩🚩. Come to think of it, if you can change the plugin request (which is hard because you don’t have the full source code, only a compiled lib), you would just remove it. However, if you can’t change the plugin, you have no way to cheat as the license key is validated on the server. The whole thing was definitely a lie.
How much was stolen
There was one more red flag. Instead of looking into the logs, Raymond asked me to send him my ads data to find out when my app had been blacklisted.
He offered a very straightforward and seemingly plausible explanation: as the revenue for 2017 was smaller than for 2016, he assumed I had been blacklisted in January 2017. However, I knew that the drop was due to the Russian government blocking us in an attempt to monopolize the mobile electronic diary market. I’ll save this story for later, but such things have almost become routine here in Russia, the most notorious one being perhaps the case of Telegram that was blocked for a few months. Anyway, spoiler alert, our little indie app didn’t give up and was soon to make $200,000/year clawing through blockages, which impressed the Russian ‘Forbes’ enough to put me on the “30 under 30” list.
To find the actual blacklisting date, one would need to find data unrelated to, but highly correlated with the ad data, and then see when the correlation stopped.
Here’s the formula: Ad Impressions = Sessions * Avg. Session Duration * Ad Duration.
The data on Sessions is collected via Google Analytics.
Avg. Session Duration is also collected using Google Analytics and is always approximately 3 minutes in my case.
Ad Duration is constant and equal to 1 min.
Therefore, Sessions * 3 = Ads Impressions. Let’s call this constant, in this case equal to 3, a sessions to impressions factor.
Now for the data:
|12 Sep 2016||24 000||55 000||2.2|
|20 Sep 2016||37 000||92 000||2.4|
|10 Oct 2016||57 000||120 000||2.1|
|11 Oct 2016||62 000||131 000||2.1|
|20 Oct 2016||70 000||147 000||2.1|
|13 Feb 2016||84 000||183 000||2.1|
As you can see, 2.1 is definitely different from 3. What is more interesting, it is exactly 3 minus 30%. This is solid evidence that I was losing 30% of my revenue for a year and did not even notice it!
Raymond accepted my proof and sent me $4K. Victory!
With all of this information on my hands, I felt that I had to warn others. I started a GitHub issue and wrote a post on the Ionic forum as the plugin was on their library list. Neither one worked. The issue was deleted, and hardly anyone read the forum post (so far there’s been 2.4k reads since May 2017). However, I did receive emails from people who were in the same situation (one of them even bought a license key, but was still getting 30% off his ad earnings), so I decided to warn everyone who was using the plugin.
Finding every user
My plan was:
1. First, to find every single app id from Google Play
2. Using brute force, to single out all the ids that return a 30% response through API (every single id gets 2%, so I could only warn users who lose 30%)
I had no idea how to get a list of ids; Google Play isn’t paginated, so you can’t just scrap it. By googling I found an existing database: however outdated and incomplete, it included public emails of developers. So I bought it.
This is not a success story
I found thousands of applications. Hundreds had the devs’ emails, of which only dozens were valid and I got replies from.
As far as I know, Raymond ignored letters from other users. I think I was the first to figure out what was going on, and he decided to pay me out of caution or, perhaps, fear. He also was kind enough to offer me a job. When I turned him down on the grounds that I don’t work for thieves, I received the following:
The plugin is still on the Ionic website, now prefixed with a disclaimer.
An important takeaway
This again raises the question of security while using third-party code, which is virtually non-existent. I still remember David Gilbertson’s article “I’m harvesting credit card numbers and passwords from your site” and the problem is things haven’t gotten any better. Even if you trust your ads plugin, every single NPM package can silently call/override methods of the plugin to replace the Ad Unit ID and steal your ads traffic.
If you are using plugins to serve ads, use those that do not allow you to change the Ad Unit ID at runtime, otherwise you can lose money.
And finally, no matter how much you dislike receiving spam, please use your real email on the app page, otherwise you won’t be able to receive an important email one day.
Founder @ Bank of Things – a physical representative of the DAO
Follow me on Twitter to be notified about new blog posts