I am building an app that downloads an XML file and ultimately presents stats for financial quarters.
If I wish to add a button that prompts the user to allow another quarters worth of data, can I simply add a boolean value to my app, send them to the store, toggle the flag and allow the download of further XML files from my website?
Read many articles on the web, but my head is spinning!
Ideally I would prefer apple to handle all the backend restoration of data on the device once it is purchased :)
Any useful links or advice would be great :)
In theory, yes. It depends how secure you want the process to be.
In your suggested way, the paid-for content (your XML files) still remain accessible to download across the public internet. You could authenticate the download, but that will require infrastructure on your end, rather than Apple's.
Basically, once a user goes off and makes an in-app purchase your app is sent back a) whether the transaction was successful, and b) if so, an iTunes receipt.
The receipt is critical, since it allows you to verify someone really has paid for the item they're trying to get. Most developers implement receipt validation on their own servers (although you can, in theory, do it on device as well).
You may decide if your app has a sufficiently small market that this isn't required. For apps where it could be quite likely people would want to pirate data, perhaps you want to consider some receipt verification.
It is possible to use a third-party service to simplify the process, if it's something you find a little too complex to integrate yourself. I've never used any myself, but one I've heard reasonable things about is Urban Airship's IAP service: http://urbanairship.com/
Related
Apple's iOS in-app purchase system has been attacked in the past by people who have tricked apps into giving them content for free. They have since improved the systems involved to try to limit this kind of thing.
I've read through the StoreKit reference documents available from Apple and I have a general idea of the workflow and the checks that need to be done, and so on. However, there may be security issues that I'm not aware of.
Can anyone provide a full list of theft-attacks that can be attempted against In-App purchase mechanisms, how developers might mistakenly allow these attacks, and what are best practices for preventing them?
These are the attacks that I am aware of, past and present:
Fake App Store
Made famous by the Russian programmer Alexey Borodin, this attack only affects apps that verify purchase receipts directly with the App Store. By modifying the DNS settings of the device, and installing forged security certificates, the verification requests are sent to a fake App Store server, which automatically returns that the purchase is valid. Unsuspecting apps will accept these verification calls and deliver the content to the user.
Commentary
After this exploit was made known in July of 2012, Apple issued updated documentation and advice for developers to ensure this kind of attack would not continue to occur. Borodin has been quoted in various web articles as stating that the "game is over" based on Apple's updated APIs and best practices guidelines.
Prevention
Apple has an entire document dedicated to this loophole here. (EDIT: Link is down, Wayback if you want...although the document covered iOS 5.1 and earlier.) The biggest point they bring up is having your app send the receipt to an external server that you own, and then having your server verify the receipt with Apple. However, if you do send the receipt directly from the app to the App Store, they recommend the following checks:
Check that the SSL certificate used to connect to the App Store server is an EV certificate.
Check that the information returned from validation matches the information in the SKPayment object.
Check that the receipt has a valid signature.
Check that new transactions have a unique transaction ID.
Fake Verification Server
If your app sends the transaction receipts to your server, which then forwards them to the App Store, one option is for the attacker to fake your verification server. By some method (altering the DNS table, changing the URL, etc.) the receipt is sent to an alternate location and a "successful verification" is returned. In this way the receipt never reaches your server and you never have a chance to check it with the App Store.
Commentary
Apparently there are a variety of apps in the Cydia store that serve to run in the background, monitor receipt traffic, and redirect it for this purpose. Source: Hussulinux Blog
Prevention
If you immediately deliver content as soon as a receipt is verified, there is no known way to prevent this kind of attack. However, take this scenario: you have a user account system managed on your own server. If the purpose of the In-App Purchase is to notify your server that a particular user account has purchased an item, and the app downloads that item from your server, you are immune to the attack. Redirecting the receipt to another server will accomplish nothing for the attacker, because your server will never mark the user account as owning an item, as it never sees the receipt.
Fake Receipts
An attacker can fake the purchase process and then send a forged receipt to your verification server. Unlike the previous attack, the receipt's outbound location is not changed, but it is replaced with an imposter. This spoofed receipt is, in fact, a valid receipt from a previous App Store transaction, and the App Store will verify it as such. By faking the purchase process and then sending a spoofed receipt to your server, the content is never actually paid for.
Commentary
Apparently there are a variety of Cydia apps that do this sort of thing. You can spot fake receipts because their product_id is totally different from anything you use in your app. Apparently the most famous spoofed id is com.zeptolab.ctrbonus.superpower1. Source: Hussulinux Blog.
Prevention
In the link where I found this attack, the blogger recommended that you unpack the receipt at your verification server (base64_decode) and check the product_id before sending the receipt to the App Store. However, in this article Apple recommends that you first send the receipt to the App Store, and then read the returned information to be certain that the receipt is valid.
(Also, correct me if I'm wrong, but Apple's recommended technique could also be used to prevent this kind of attack even if you don't have a verification server. If your app sends the receipt directly to the App Store, it could examine the contents of the JSON response to ensure it's valid. But this goes against Apple's recommended best practices of using an external verification server, so I wouldn't advocate it.)
In Closing
These are the attacks that I'm aware of, feel free to correct me if I'm wrong on any point or to put forth additional attacks and fixes.
As a note, there's this website: http://www.in-appstore.com/ which claims to allow in-app purchases for free, either on iOS 5 or with a jailbroken iOS 6 device, and is active as of July 5th, 2013. While I'm not 100% sure how they are doing it, it definitely seems to involve DNS rerouting and faked security certificates, which would imply Fake App Store or Fake Verification Server, which would additionally imply that there are still apps out there that are not secured against these attacks.
Resources
Apple iOS in-app purchase hacking
My Experiences With Verifying In-App Purchase Receipts
How to detect "IAP Crackers"?
EDIT:
Additional
It seems like one or two people have swung by here and found this post useful, and I'm glad.
There's more information that can be had on this subject, either in other posts, books, or, if you're up to it, scouring the underbelly of the internet. Here's just a couple of websites and posts and so forth that I want to look into, but haven't had a chance yet. I'll add more links later when I find interesting tidbits.
http://www.se7ensins.com/forums/threads/tut-how-to-hack-ios-games-and-apps.701845/
http://www.iapphacks.com/
A couple of immediate takeaways: don't store your player's data in a simple plist unless you want it to be edited by some teenager. People don't have to hack your IAP system if they can just give themselves gold or something similar by editing the files on the disk. Perhaps by encrypting these files, you could discourage a certain segment of attackers.
Based on the se7ensins link, it seems as though an attacker can also pry apart your binary and mess with it to achieve the same ends as editing a plist file, or even more, but this will require a slightly higher skill level. Perhaps setting up jailbreak detection would suffice to deter most people who would resort to this.
Again, this section is mostly speculation, but it may help someone. Really, the level of protection you have depends on how far a developer is willing to go (down the rabbit hole of security and encryption) to protect their bottom line.
I have a very strait forward question (and yes I've looked though apple documentation to see if this has an answer but no luck... I may have accidentally missed it though)
Here's my plan:
The problem I've been trying to find a workaround for is that if the admin would ever want to add a product, he would have to log into iTunes connect to add it and also add it in a custom control panel. We, obviously, don't want to make him suffer that so I've been looking for a solution but I need you guys to tell me if it's allowed by apple. Basically I will take over most of the product handling on our servers and will only go to apple with the transactions. This means that apple will not have an in-app purchase set up for ALL the products... only one for each length of subscription (1 month, 3 month... etc) and a few consumable in-app purchases for the various prices of the issues/singles
Side note: I will be selling monthly issues that contain multiple singles for each day of the month. The user will be able to download a full month or a single day at a time if they like.
DEFINITION OF CONSUMABLE PURCHASE - products must be purchased each time the user needs that item. For example, one-time services are commonly implemented as consumable products.
So I will store all the information in our server about the products and if someone chooses to buy a single month's issue that was set to 4.99 (on our server, not apples) then the app will run the in-app purchase with apple that is listed for the 4.99 tier. Whenever a person opens the app for the first time, their app will send some information to our server and they will have a row set aside for them where all the information about their purchases will be recorded so that they can restore them if they switch over to another device.
If you guys think i'm safe in doing this, please let me know so that I can proceed. Also, if this method helps anyone, feel free to use it!
Thanks,
Matt
I think your restore process might be flawed. You talk about the app sending some information up to your server, but what is that information? There is no reliable way to uniquely identify a user across different devices.
If you want to continue on this path you'll want to make sure that your recovery and failover process is very solid. Try out every imaginable scenario. From an app store submission point of view, you'll want to consider a token/coin-based approach. Of course, Apple's guidelines are fairly loose and subject to change so it's always possible you'll get rejected, but tokens are certainly more solid than simply using the same generic in-app purchase.
In a token system, you would set up in-app purchases for different numbers of tokens that the user can purchase as a sort-of virtual currency only valid within your application. Then users can spend these tokens on any items that you dynamically create.
Server-side this means you'll need some way to store how many tokens a user currently has and a way to uniquely identify a user across devices, which is a fairly uncertain proposition. Instead of storing the number of tokens each user has, you could implement some sort of hashing algorithm that generates a hash from an in-app purchase receipt and then sends it up to your server. If the app crashes or the network dies after purchase but before sending your hashes up, next time they open the app you can recalculate all of the hashes, send 'em up, and if the server doesn't recognize a hash it just adds it to the database. Then if a user wants to restore their purchases you simply recalculate the hashes on the device using the in-app purchase receipts you'll receive and then send them up to your server and ask the server to figure out for each of those hashes, how many tokens the user has left. You could think of it like a gift card system, where each hash is one gift card.
Again, app store rules change and if apple thinks you're trying to game the system and not provide a useful experience they have the right to reject you. It could be worthwhile to open a Developer Technical Support request and see if an apple engineer can provide you with a better solution or tell you if the reviewers are likely to accept your application.
I have two similar apps with in-app-purchase (IAP) content that could be shared between them. I'd like to reward customers who buy in one app, by letting them transfer the purchase to the other app. However, I'm worried that my apps would be rejected due to the App Store review guideline that says you can't have any non-App store content activation methods.
As far as technical feasibility, it's clear to me that the Document Interaction mechanism is a means to this end (sans web server). I can have each app register a custom file type. The app in which the user purchased the content can show a link to launch the other app, passing it appropriate metadata as the "launched file" so the second can then mark the items as purchased.
Does anybody know if this has been attempted, and if Apple is approving such an approach?
Note that I'm not concerned about purchase security with this approach, because making paying customers happy is much more important to me than preventing piracy.
This isn't so much an answer to the precise question above as it is a useful alternate technique of accomplishing the end goal. If you set things up correctly, two apps can share KeyChain access, and thus share metadata about purchased IAPs. This requires using the same Bundle Seed ID (e.g. "AXGUKHGX...") for the app ID, in combination with setting things up properly in your app's info plist. This latter technique is a much more elegant approach for propagating sharable IAPs.
I'm building an app which I intend to distribute through the Mac App Store. I will use in-app purchases to allow users to buy "credits" which they can consume in the app. I will use Apple's IAP APIs to handle the money transaction side of things, but I'm wondering how I best go about securely storing the current balance of credits.
Obviously, I'd like to avoid "clever" users from messing with my app's files on disk to increase the number of credits, so at the very least I need to encrypt this file. But even that is not sufficient, because a user could simply restore from a backup copy to restore their credit balance.
One obvious option is to run my own webserver and have the app connect to that for every transaction, but that sounds cumbersome. I've looked for virtual currency services for iOS (since this is much more common in iOS apps), but most (all?) of them have some cross-marketing angle to them, forcing me to put ads in my app which I don't want. I will gladly pay for a service with a simple API as long as it's completely transparant to my users. E.g. I don't want my users to have to sign up for an account on some 3rd party's website.
What are my options here? Any advice?
IF you actually want any real security, you need to use a server.
No matter what kind of cryptography you do client side, users can always reset the state of the app and then add the receipt for IAP that you will then validate. In short, they can always erase the phones memory that they consumed those credits.
If what they are purchasing is only in the app(i.e. its just programaticly unlocked functionality) and is not provided by an outside server/ service, then a sufficiently motivated user( likely with a jailbroken phone) could simply tweak your code to provide that functionality. So you can't have real security in that case. Your best bet is just obfuscation.
I read (almost) all the answers on verifying in-app purchase, and actually I already implement it in a server-side fashion. But managing a server sometimes could be too much expensive, and in theory you could do the verify from your app: basically is just sending a json to Apple and get the answer back.
Of course I know that on jailbroken devices the receipts may be fake (that's why you verify them) but (I beg pardon my ignorance) why I can't trust an https connection to the Apple server?
I mean if the user hack my app, there's no real way to be sure of anything, but if the hack is a general method to provide fake receipts testing with Apple could be enough right?
To be clear, what is the security level of an in-app verify of recipts? Can it add some degree of protection os is useless?
This answer explains quite well why you must use server side checking to limit the effect of some "general purpose" crackers, like "IAP cracker"; besides chaining the iTunes json request in your content delivery API is quite convenient and the answer is fast.
Of course if your aim is to provide some content already in the app but locked, you may feel it is not convenient to setup a server specifically for this, but I will ask you to do this experiment:
make an app with some good content and this content already locked in the app (so no content server need)
add some analytics just to track the usage of this locked feature
after some month, compare the number of purchases with the number of new users using the paid feature.
at this point it will be clear for you that adding a server script just for receipt validation is a good investment; besides there are some services, which are very cheap (e.g.: urban airship) we already do this for you, so you don't need to setup an hardware for this.
I hack inapp cracker and discover a way to block it client side: the receipts and transaction IDs it creates have a predictable scheme that's easy to spot. I put all the details here:
spot fake receipts client side
update
hope this helps