An ad plugin was stealing 30% of the revenue for a year and I didn’t even notice

An ad plugin was stealing 30% of the revenue for a year and I didn’t even notice

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

At that time, my app was built on Cordova (Ionic), a framework for building HTML5 mobile apps. Cordova doesn’t have direct access to iOS or Android API via JavaScript; you have to use plugins and call them via the bridge. The same applies to React Native and Flutter.

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.

A bit old fashioned meme but seems to fit

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.

This is my revenue data. Pauses in revenue are explained by the specifics of the application – we receive revenue while the children go to school. Children don’t go to school in the summer.

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:

Date Sessions Ads Impressions Factor
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:

Should I sell it as an NFT?

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.

Kvirkvelia Levan

Founder @ Bank of Things – a physical representative of the DAO

Follow me on Twitter to be notified about new blog posts

NOW WITH OVER +8500 USERS. people can Join Knowasiak for free. Sign up on
Read More

Ava Chan

Ava Chan

I'm a researcher at Utokyo :) and a big fan of Ava Max