Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why one should not call receipt validation endpoint directly

Apple provides an endpoint to validate receipts: https://buy.itunes.apple.com/verifyReceipt and warns against calling the endpoint from the app

It is not possible to build a trusted connection between a user’s device and the App Store directly because you don’t control either end of that connection, and therefore can be susceptible to a man-in-the-middle attack.

It is stated, that the safe way is to send the receipt to "my own" server firstly, then communicate with Apple endpoint from the own server.

Honestly, I do not understand how does it help to increase the level of security. Yes, I do not control the /verifyReceipt endpoint, but Apple hopefully does. And why

phone <-> my server <-> Apple server is better than phone <-> Apple server?

Could you elaborate on this from point of view of the hacker (or man-in-the-middle)? How would he tamper the receipt/response in the latter case and what makes it difficult for him in the former case?

like image 654
Nick Avatar asked Sep 18 '19 08:09

Nick


2 Answers

It's relatively easy to change an app binary to alter a string within the app. If your binary contains a string "https://buy.itunes.apple.com/verifyReceipt" then an attacker can change the string to "https://example.com/verifyReceipt" (a server that's under their control) and have the server return the receipt JSON that makes it seem like a purchase was successful. This is an easy attack to automate, so you just run a binary through a script which replaces all instances of the Apple URL with another URL.

When you communicate with your own server to Apple you can be (relatively) sure that that connection is secure. There are also ways to secure the communication between the app and your server such as a certificate in the app binary with a public key, the private key on your server. (I'm not an expert at this part so the details about keys might not be 100% correct).

All this being said there are other ways an attacker can make it look like a purchase went through. They can search your app binary for common receipt parsing libraries and flip known booleans (e.g. a userCompletedPurchase boolean flag). These attacks are easily scriptable.

The best way to make sure that your app isn't attacked is to remove the low-hanging fruit and make it that much more difficult that the common scripts won't open your app to attack. One way to do that is to not verify receipts directly with Apple.

like image 195
nevan king Avatar answered Nov 06 '22 20:11

nevan king


I think that the key part to the section from Apple documentation that you cited, but didn't include, was the sentence before.

Using your own server lets you design your app to recognize and trust only your server, and lets you ensure that your server connects with the App Store server.

In particular the first half of that sentence (emphasis mine). I see this as a bit of nudge from Apple that the app should be designed as such to "recognize and trust only your server".

In the simplest case (ie. minimal), one could use their server as a proxy to reach Apple's server. The server could simply pass Apple's payload back to the app, or maybe send some simple JSON like

{
    success: true
}

Or maybe even it's something as lazy as just sending a 200 response.

Using MITM, it's easy to change the response as needed. So even though you are using your server, the only barrier at this point is the attacker would need to determine what a valid response looks from your server.

They may be able to figure it out by simply sending a bad receipt and then seeing the response. Or maybe a hacker will TOFFT and just make a purchase to get the valid response and then provide others so they can profit.

This is "one step" above going to Apple directly, because everyone knows what the Apple payload is. Thus if the app goes directly to Apple it's easier for someone to be able to run a MITM and replicate a valid receipt response.

Going back to what Apple wrote, they are encouraging you to have a design that is more robust to help mitigate potential fake purchases from occurring. This robustness is what protects you more.

This can take the form in many ways.

For example, perhaps your server sends back the response in an encrypted format. Or replies with a hash. Even better if your app relies on your server through the course of usage, so the server can act as the truth. Or maybe the app periodically "phones home" to get a config of privileges. There are numerous ways one can make it more difficult for a hacker.

Apple is leaving to you just how you determine that trust with your server is established. It is after all, your "money".

As an example, the latest game I've made is specially built to use the server as the truth. So all moves go through the server (game is simulated on the server). While someone could certainly modify the app, in the end the server should theoretically correct any badness introduced.

Note, that it still is possible that someone can bypass even more robust security measures.

like image 20
Mobile Ben Avatar answered Nov 06 '22 19:11

Mobile Ben