Validate your in-app purchase receipts

By | | 3 minute read

I’ve been keeping an eye on the Russian hack reported a while ago. Recently I wanted to see how widespread the hack was on Toshl for iPhone and was startled by what I saw.

About 30% of all in-app purchases on `toshl are attempts using the Russian hack from a couple of weeks ago. Validate your receipts.

— Miha Hribar (`mihahribar) August 28, 2012

I did take into account the number of duplicated requests by folks that tried the same hack a couple of times, but still it appears that the hack is more widespread than I first thought. Toshl was not affected by the hack, because we do our receipt validation on the server-side, but seeing the number of attempts piqued my curiosity.

How the hack works

Since I am a registered iOS developer this line is a prerequisite: “The first rule of iOS hacks is you do not talk about iOS hacks”. But in the spirit of learning and better protecting your apps in the future, some research is warranted. Here is what this hack does at a high level:

How to protect yourself client side

When the hack was detected Apple quickly notified it’s developers, amending the documentation and releasing this sample code. The main points for avoiding this hack seem to be:

The documentation states that the hack does not work in iOS6, so I guess all the verification steps have been included in StoreKit itself, which makes you wonder why this was not done in the first place.

How to protect yourself server side

Having the receipt verified server-side does not make you completely immune to the hack. While you are connecting to the correct server for verification (unless your network was compromised as well), the receipt returned from the fake App Store server is in fact a valid transaction that can be restored, so additional steps need to be taken:


Since it will take a couple of years before all iOS 5.x versions are gone from this world, SSL verification will remain a key for preventing this hack on the client side and keeping track of the product_id and tranaction_id on the server side.