It seems like the Black Friday has come earlier on Google Store.
On Oct 29, Dominik has discovered a critical vulnerability on the Google Play In-App Billing Library, which allows attackers to bypass the in-app billing verification process – in short, you can get everything for free!
As of Nov 4th, Temple Run 2 is still vulnerable. Some apps like Clash of Clans mitigated this vulnerability by disabling the in-app purchases to all those haven’t upgraded to latest version – Android only.
The In-app Billing Verification Mechanism
When a user making an in app purchase, the app will actually get a piece of data from Play Store. The local Android app will verify the data to determine whether the purchase is successful, then give corresponding response, i.e. add you some coins or display a “purchase failed” message.
If a user could forge the reply data, make it passing the verification, then he/she would get things for free. To prevent that, Play Store applied a public-key verification mechanism using the RSA algorithm. The reply data(a JSON string) will be signed by a private key which stores only on Google server, which makes it impossible for a 3rd party to forge. The user device will own the public key to decrypt it. If the data could be decrypt properly and verified, then we can guarantee the reply is from Play Store.
The Logic Flaw
Let’s look into the critical verification function, which supports 3 parameters:
– The public key for verifying(base64 encoded)
– The replied data
– A signature to verify the integrity of replied data, signed by private key as well
Relating source code is as followed (https://github.com/dschuermann/billing-hack/blob/master/src/org/billinghack/google/util/Security.java#L73):
So, first it will check whether the reply data is empty, then check if the signature of reply data exists, if exists, start verifying the reply data by using public key. Wait… what if the signature is empty? The function will RETURN TRUE, letting us pass the verification?
It’s a simple logic error: the developer forgot to add the “else” branch.
Here is the fixed code. In the fixed version, if any of the 3 parameters is empty, the verification will fail.
As elaborated above, to exploit this vulnerability, we need to send a empty string to the 3rd parameter of verifyPurchase method. Dominik has released a PoC code (you could also find it on https://github.com/webfiltering/billing-hack). It’s a 3rd party app that can add a high-priority intent-filter to intercept the InAppBillingService.BIND intent:
Therefore, every time the library verifies a purchase, we could intercept at first hand, modify the signature to empty. Afterwards, every purchase on the phone will be free of charge.
Here is the code for modifying the parameters: