1

I have set up in app purchase receipt verification in accordance with Apple's recommendations by sending the receipt to my server which in turn sends it to Apple's servers for verification. All my receipt processing is handled server side and it is working perfectly. My server sends back a very obscure code to my app to confirm whether the purchase is valid or not. I make use of a pretty robust obfuscation method on the app side to disguise what is going on with that return code to make it as difficult as possible on jailbreaking hackers to defeat it.

The issue is that I have my php files stored in a password protected folder on my web server, and am concerned about how that can be considered secure when the app itself has the user name and password for that directory embedded in it to send the receipt to the php file to begin with.

My app only uses the server for receipt authentication of in app purchases. All other functionality is in the app itself, so I don't force each user to have an account with a unique username and password.

I am using URLSession to communicate with the server via a TLS 1.2 https connection so that part is secure, but I can't think of a way to keep a determined hacker from potentially extracting the user name and password from the app on their device, and having access to my server folder directly. Someone with that capability could just as easily modify the php file to always return a code indicating a valid purchase.

I do obfuscate the user name and password inside the app to the point that I think most folks would probably give up on trying to figure it out, but I know I have only made it harder to extract, not anywhere near impossible.

Any thoughts on this? Just about everything I found online concerning this has been concerned with not transmitting a username and password via http, not the bigger issue of a jailbroken device.

Scooter
  • 4,068
  • 4
  • 32
  • 47
  • Why do you include username and password into your app? Just use a randomly generated token that is checked e.g. by the PHP script on server side and that is only useful for that specific API. – Robert Mar 07 '17 at 19:22
  • Robert I am fairly new to interacting with a server from an iOS app. The server directory is password protected using a .htaccess file. I am using basic authentication with NSURLSession to access the .php file. I guess the question I am asking is how to grant access to this protected directory without a hardcoded password and username. – Scooter Mar 07 '17 at 19:29
  • Do not use basic auth, just use an HTTP get parameter and check that in the server side PHP script. Of course you have to learn a bit PHP for that. Again: NEVER EVER EMBED WEBSERVER CREDENTIALS THAT ALLOW DIRECT FILE ACCESS INTO AN APP! – Robert Mar 08 '17 at 09:00
  • I think I am missing a critical detail from your advice. To give a quick rundown of my implementation so far, I have a pretty robust .php file on my server that receives an https POST parameter from my app, passing along the json of an Apple receipt so I can verify it server side. That .php file lives in a password protected directory on my server, so my app (which is using NSURLSession to connect to the server) receives an authentication challenge and has to respond with a user name and password. How would using GET work any differently? Would I not still receive a challenge? Thanks!! – Scooter Mar 08 '17 at 12:20
  • What method do you use for "password protected folder"? Hopefully this means you have using an `.htaccess` file or something similar. – Robert Mar 08 '17 at 14:04
  • I am using .htaccess, hence NSURLSession receiving the authentication challenge. Could it be as simple as parking an empty index.html file in the directory alongside the .php files and then NOT using .htaccess? From what I have read, an Apache server will never allow file access to a folder with an index.html or index.php file in it. If that is true then maybe there is a simple fix for this. I suppose I could also put a very simple .php file in the public_html folder, that accepts the json from my app, and then forwards that along to the .php file that is inside the restricted folder. – Scooter Mar 08 '17 at 16:19
  • Of course, I guess that would prevent my app for having access to it to. – Scooter Mar 08 '17 at 16:21

2 Answers2

1

So I think I have come up with a fairly secure solution to this mess. Thanks much to the folks that took the time to comment on this, as your inputs were certainly helpful.

First off, while I have quite a bit of experience with Obj-C/Swift iOS development, the server side stuff is pretty new to me, but I am learning a lot pretty rapidly. What may seem like a huge eureka moment to me, will seem fairly routine to a big-time REST/Linux/PHP expert, so bear with me.

To summarize the challenge: I wanted to send a json representation of an in-app purchase receipt from my app to a .php file on my server so it could send it to Apple for verification. To protect that .php file, I placed an .htaccess file in its folder to require a user name and password to access it.

NSURLSession dealt with this nicely, but required me to put the user name and password in the app...not good. That is what got the obfuscation conversation going, and made me realize there was no way to keep the password safe when hardcoding it into the app.

Then I realized that I could park files outside of my public_html folder (my eureka moment), and that is what I have done. So inside the public_html folder, which has an index.html file in it as well, I now have a very simple .php file that does nothing more than call a function in another .php file which does all the work talking to Apple's servers and parsing the response. When it has finished parsing, it returns a very obscure code (not the well publicized codes that Apple returns) to the simple .php file which in turn returns that to my app.
Based on that code the app will decide whether or not to grant access to the purchased goods.

Using server side permissions I have restricted the simple .php file in the public_html directory from read or write access from the "world", leaving it as executable only. So while a hacker can quickly obtain the name of that file if they hack the app, it should do them no good. I no longer require a user name or password in the app at all, and the "main" .php file that does all the work lives in a folder that is outside the public_html folder, has its permissions set to restrict read/write/execute from the "world", and even though I think it is overkill I put a .htaccess file in there and deny all.

I think I have a "fairly" secure solution here that should make it pretty hard on a casual hacker to steal an in-app purchase, but as always I am open to suggestion in case I have missed something.

Scooter
  • 4,068
  • 4
  • 32
  • 47
0

You are imagining a hacker reversing your obfuscated binary to try to get the username and password. That's the hard way to do it. The easy way is to inspect network traffic.

Yes, the TLS can easily bypassed by the owner of the device even without jailbreaking it. TLS protects against external attackers, but it does not protect against something wanting to inspect their own network traffic. This is very easy to do, see for example instructions on my blog where I beat a very popular iOS game.

If you want to stop this easier attack, you can try to implement certificate pinning. That can still be broken easily on a jailbroken device, but you deter a lot of casual hackers who won't want to jailbreak their device.

At the end of the day, you are right that a determined hacker is going to win against this type design.

TheGreatContini
  • 6,429
  • 2
  • 27
  • 37
  • Thanks for the thoughtful reply. I will indeed look into certificate pinning, but the funny thing that is the deeper I dig into this issue the more vulnerable I feel. I have at this point probably spent more time trying to secure the in-app purchase than I have spent writing the app! Of course this time is not wasted as I will be able to back fit the rest of my apps with this as well once I perfect it. Thanks again. – Scooter Mar 06 '17 at 21:26
  • @Scooter: You're right. You are fighting a battle that may be more effort than what it's worth. Especially, proper implementation of certificate pinning can be a PITA. But I hope you get the takeaway from my post: all that obfuscation is pointless if there is a much easier way for an attacker to succeed. Intercepting the network traffic as described above is just about always the first thing an attacker is going to do. – TheGreatContini Mar 06 '17 at 22:19
  • I did get your point, but it is all in there anyway at this point. It has really become more of an interesting intellectual challenge for me now. I am curious how bank level security defeats this. I guess forcing folks to register an account on my server would add a level of difficulty for a hacker. I need to study up on tokens as well and get away from basic level server authentication. It is certainly a lot of cat and mouse! – Scooter Mar 06 '17 at 23:29
  • @Scooter, hiding secrets in client side code is a losing battle, even for banks. In regard to bank code, Cert pinning gets implemented sometimes. Jailbreak detection gets implemented sometimes, but usually can be bypassed with little effort. Code obfuscation is used less often, mainly because the good obfuscators are expensive. Truth is you shouldn't care if a single user can bypass your control, the more serious concern is if somebody develops an app that cheats for everybody. The AppStore is more controlled than the Android alternative, which works in your benefit. – TheGreatContini Mar 07 '17 at 02:36
  • And all this for an app that might make $30.00 in a good month lol. It is not much of a target, but you never know when I might drop the next Angry Birds on the market. – Scooter Mar 08 '17 at 02:06