How to securely enable a feature after validating in-app purchase - ios

I'm working on an iOS app, but if there is an answer here, it may apply to other platforms as well.
There are basically two ways to validate an in-app purchase: locally and server-side. The server side method is documented here. (I can't find the docs for the local method at the moment.)
Let's say I validate the purchase server-side. My question is about what happens after that, to enable the purchased feature(s). I don't see documentation on this. Am I missing it?
I imagine two or three steps:
Server sends an HTTPS response to the iOS app, saying "yes, you made X purchase".
The app flips some boolean variable in memory to enable the purchased features.
[Maybe] The app saves this state to local storage so that it doesn't need to revalidate the receipt via the internet every time it launches.
All of these steps seem vulnerable to attack on a hacked/jailbroken client device. Obviously there are tradeoffs between the difficulty of hacking and the cost of the in-app purchase and potential lost revenue. I'm thinking about the case where the app is more expensive or popular and there may be incentive to hack it.
Example possible vulnerabilities: (again, all of these probably require a helpful - to the hacker - OS kernel)
a real server response could be sniffed and inspected and then faked for other users
the app's memory could be inspected and the boolean variable flipped
if the state is saved (for example, in a file, or in the user defaults key-value store) that state could be altered
So, are there some techniques to mitigate or prevent these hacks? Or do companies simply accept that a determined hacker can steal software, and take it as part of the cost of doing business?

Don't know if there is a "correct" answer here since you outlined it pretty well:
Obviously there are tradeoffs between the difficulty of hacking and the cost of the in-app purchase and potential lost revenue.
If there was an official way of handling this then it does just become a target for hacking.
Most apps I've seen (even large ones) are keeping data in local storage to determine purchase status. But... you can keep this data on a short cache and refresh it in the background every 5 min or so. That way a hacker would need to overwrite it every 5min which makes normal usage pretty impractical.
Unless you have a high cost of supporting users (e.g. Spotify paying licensing costs) then there's probably better areas to invest in than this.

Related

FCM device groups vs topics

I'm developing an iOS app that sends notifications to individual groups of users. Number of users per group will most likely be in the order of 1-7, but can exceed that and while the app generally doesn't set a limit, I hardly see it exceeding 20.
Currently I've set it up with the topics approach and it works like it should. I understand this approach is optimized for throughput rather than latency, as opposed to device groups.
Nearing completion of my app, I'm considering to change to device groups. However, I don't see many advantages, especially considering the substantial complexity that comes along with it.
Notifications at the moment is fast enough. As long as delivery time doesn't suddenly increase by a lot, it's perfectly fine at the moment.
How secure are topics compared with device groups?
The app does allow the user to use more than one device, but I don't see that happening often - realistically quite seldom. However if that were to happen, device groups would handle it better. Still, I think it's an acceptable compromise to stick with topics.
For device groups to work, I have to create a new collection server-side to manage device registration tokens and their updates, pairing with my existing data structure and implementing several http requests. I also need to query for the notification_key every time I want to send a notification, instead of sending it to the more obvious id I now use for topics.
I've read through other questions on SO, but wanted to get some fresh thoughts on this. My opinion is to stay with topics unless convinced otherwise
I'm using both of these delivery methods and yes, topics are far easier to manage but that comes at a cost of security. If your groups are public in nature then you should be fine with topics. If they're meant to handle more sensitive/private information you should probably go with device groups / individual tokens. Reason being, topics are more public facing and anyone can listen in on them, even devices not on your app.

Should I worry about my API Keys being extracted from the iOS app

I need to make requests to the Google Books API form my app which includes the API key in the URL.
I thought about just creating it as file private variable in my app, though this is a big problem because it would then be uploaded to Github.
Then I thought about environment variables but I heard they aren't included if the app isn't run by Xcode.
I'm aware that this way the key could be extracted, but should I worry?
Can't users anyway just use Wireshark or something similar and see the key in the URL?
And I can restrict the key so it is only valid when called from my Bundle ID.
What do you think would be the best option for making the calls? I mean other than that, the app barely gets 10 downloads a week so this can't be too big of an issue, right?
Whether it is an issue entirely depends on your usecase and threat model. Consider your api key public if you include or send it in any way in/from your app, and think about things like what can people do with it. What level of harm can they cause you? This gives yo the impact. Would they be motivated, for example is there a financial benefit for them somehow? This estimates the likelihood of this happening. This together, impact x likelihood = risk, which you can either accept (do nothing about it), mitigate (decrease the impact or likelihood), eliminate (fix it) or transfer (rg. buy some kind of an insurance).
As for mitigations, can you limit the api key scope, so that only necessary things can be done on the api with it? Can you set up rate limiting? Monitoring, alerting? I'm not familiar with the Books api, but these could be mitigating controls.
As for eliminating the risk, you should not put the api key in the app. You could set up your own server, which would hold the api key, and would pretty much forward requests to theBooks api, augmented with thr api key. Note though that you would still need some kind of authentication and access control in your server, otherwise it can just be used as an oracle by an attacker to perform anything in the actual Books api the same as if they had the key, only in this case they don't need it. This role could also be fulfilled by some kind of an api gateway, which can also add data to api queries.
Eliminating the risk is obviously more expensive. Defenses should be proportionate to risk, so you have to decide whether it is worth it.

How much access will my users have to a SQLite Database I ship with my app?

I'm developing an iPad app that will rely on a very large database of valuable information. I'm not too familiar with the device myself (I don't have a personal iPad, nor have I ever used one outside of developing this app). Users cannot directly see the data in the database through my app anywhere.
Would there be any other way users could get access to the data in my database (perhaps by plugging the device into the computer and going through Xcode or iTunes)? If not, I've been reading up on jailbreaking a little, and I've seen that doing so can allow a user access to the device's filesystem, so would that allow them to see the contents of my database? Or would it be possible by jailbreaking and installing an app to view database files on jailbroken devices (in fact this question would suggest that it could be quite easy to develop a "database reader" app for jailbroken devices)?
If the database is there, then people can touch it. It's just a matter of being a little more than a power user. They might not be able to read the data from the database if they don't have the credentials to authenticate into it, but then again once you have a database in your hard disk, it's just a matter of patience and knowledge to break into it.
This is a principle that applies to any device and operating system, not just iPad and iOS. If you don't want your users messing up with some file your app uses, you may encrypt it with an obscenely long encryption key. Someone may eventually crack that info... All you can do is ensure that they won't be able to do so before your app is obsolete anyway.
Otherwise, keep your data in a server, where people can't touch it.
I am a Developer (not a hacker) no matter how hard I try to defend my apps, as soon as the code or database is on the device (encrypted or not) I treat the data as public. if the decryption key is passed to the phone and decrypted on the phone, then consider that data public too. basically you are screwed. Give up defending your apps. and just start building cooler stuff, and use HTTPS when sending data over the internet, thats all I can ask for. Defending your keys, api tokens, high scores, coins, etc.. is quite literally impossible. yes do a little to try, but your efforts are fruitless. Every day the public hacker tools to see inside locally encrypted databases, locally encrypted apps, see inside obfuscated apps, is getting better and better every day. you can't beat it. developers are not smarter than hackers, period. Giving the end user a false sense of security. its like locking your house, or locking your car, can you stop someone breaking in? nope. the only way to solve it is to build a big ass bank (aka server), put some tellers at the front desk (aka cloud API), and be done with it.
I'm not an IOS developer, but I do know SQLite. You can encrypt databases in SQLite - look for sqlite3_key_v2() documentation. Your application will need to have the password internally, but you can make it difficult for a hacker to get at that. Don't use a static string as your password - instead take some string and then manipulate it programmatically. This will make it more difficult, though not impossible for an attacker to recover the key. But it will add an order of magnitude more complexity to get at. The attacker will have to get access to the database file itself, and then will have to reverse engineer your app in order to recover the database password.

iOS App Offline and synchronization

I am trying to build an offline synchronization capability into my iOS App and would like to get some feedback/advice from the community on the strategy and best practice to be followed to do the same. The app details are as follows:
The app shows a digital catalog to users and allows them to perform actions like creating and placing orders, among others.
Currently the app only works when online, and we have APIs for all actions like viewing the catalog, creating/placing orders which return JSON data.
We would like to provide offline/synchronization capability to users, through which users can view the catalog and create/place orders while offline, and when they come online the order details will be synchronized and updated to our server.
We would also like to pull the latest data from the server, and have the app keep itself up to date in case of catalog changes or order changes that happened at the Server while the app was offline.
Can you guys help me to come with the best design and approach for handling this kind of functionality?
I have done something similar just in the beginning of this year. After I read about NSOperationQueue and NSOperation I did a straight forward approach:
Whenever an object is changed/added/... in my local database, I add a new "sync"-operation to the queue and I do not care about, if the app is online or offline (I added a reachability observer which either suspended the queue or takes it back working; of course, I do re-queueing if an error occurs (lost network during sync)). The operation itself reads/writes the database and does the networking stuff. My ViewController use a NSFetchedResultsController (with delegate=self) to get callbacks on changes. In some cases I needed some extra local data (it is about counting objects), where I have used NSManagedObjectContextObjectsDidChangeNotification.
Furthermore, I have used Multi-Context CoreData which sounded quite reasonable to use (I have only two contexts).
To get notified about changes from your server, I believe that iOS 7 has something new for you.
On the server side, you should read a little for the actual approach you want to go for: i.e. Data Synchronization by Dan Grover or Developing Android REST Client Applications (of course there are many more good articles out there).
Caution: you might be disappointed when you expect an easy solution. Your requirement is not unusual, but the solution might become more complex than you expect - depending on the "business rules" and other reasonable requirements. If you intelligently restrict your requirements you may find a solution which you can implement yourself, otherwise you may also consider to use a commercial product.
I could imagine, that if you design the business logic such that it takes an offline state into account and exposes this explicitly in the business logic, you may find a solution which you can implement yourself with moderate effort. What I mean by this is for example, when a user creates an order, it is initially in "not committed" stated. The order will only be committed when there is access to the server and if the server gives the "OK" that this order can actually be placed by this user. The server may also deny the order, sending corresponding messages to the user.
There are probably quite a few subtle issues that may arise due to the requirement of eventual consistency.
See also this question which contains pointers to solutions from commercial products, and if you visit their web sites give valuable information about the complexity of the problem and how this can be solved.

Storing a small number of images with potential for IAP

I'm making an app. Part of the app is to choose from 5 preset images.
These will be available at install and so need to be bundled with the app.
However, there is also potential to "add" more images through in app purchases.
I'm looking for the "best" way to store these images on the device with the potential to add/unlock more images.
My thoughts are that "CoreData" is too heavy for this. I could do some sort of plist thing to reference the initial five images. But then how do I add more through IAP?
With IAP, do I download the additional images upon purchase? Or should they also be bundled into the app at install and then unlocked when purchased?
Never done IAP stuff before and my previous apps all used Core-Data as they were very data heavy.
There are two things to consider -
Do you want to add more images after you've shipped?
Are the images small enough that they can be download quickly on demand?
If the answer to either is yes, I would recommend going the hosted content route. Apple even allows you to host content on their servers.
Otherwise, just bundle everything in your app and unlock as required.
Small note on security: I would not worry about piracy at all since there is no way you can stop people from pirating content/apps. Besides, the number of people who JB is quite small (23m / 90% * 500m ~ 5%) and the number of people who pirate is even smaller.

Resources