Can I prevent an iOS user from changing the date and time? - ios

I want to deploy managed iOS devices to employees of the company, and the app they will use will timestamp data that will be recorded locally, then forwarded. I need those timestamps to be correct, so I must prevent the user from adjusting the time on the device, recording a value, then resetting the date and time. Date and time will be configured to come from the network automatically, but the device may not have network connectivity at all times (otherwise I would just read network time every time a data value is recorded). I haven't seen an option in Apple Configurator to prevent changing the date and time, so is there some other way to do this?

You won't be able to prevent a user either changing their clock or just hitting your API directly as other commentators have posted. These are two separate issues and can be solved by having a local time that you control on the device and by generating a hashed key of what you send to the server.
Local Time on Device:
To start, make an API call when you start the app which sends back a timestamp from the server; this is your 'actual time'. Now store this on the device and run a timer which uses a phone uptime function (not mach_absolute_time() or CACurrentMediaTime() - these get weird when your phone is in standby mode) and a bit of math to increase that actual time every second. I've written an article on how I did this for one of my apps at (be sure to read the follow up as the original article used CACurrentMediaTime() but that has some bugs). You can periodically make that initial API call (i.e. if the phone goes into the background and comes back again) to make sure that everything is staying accurate but the time should always be correct so long as you don't restart the phone (which should prompt an API call when you next open the app to update the time).
Securing the API:
You now have a guaranteed* accurate time on your device but you still have an issue in that somebody could send the wrong time to your API directly (i.e. not from your device). To counteract this, I would use some form of salt/hash with the data you are sending similar to OAuth. For example, take all of the parameters you are sending, join them together and hash them with a salt only you know and send that generated key as an extra parameter. On your server, you know the hash you are using and the salt so you can rebuild that key and check it with the one that was sent; if they don't match, somebody is trying to play with your timestamp.
*Caveat: A skilled attacked could hi-jack the connection so that any calls to example.com/api/timestamp come from a different machine they have set up which returns the time they want so that the phone is given the wrong time as the starting base. There are ways to prevent this (obfuscation, pairing it with other data, encryption) but that becomes a very open-ended question very quickly so best asked elsewhere. A combination of the above plus a monitor to notice weird times might be the best thing.

There doesn't appear to be any way to accomplish what you're asking for. There doesn't seem to be a way to stop the user from being able to change the time. But beyond that, even if you could prevent them from changing the time, they could let their device battery die, then plug it in and turn it on where they don't have a net connection, and their clock will be wrong until it has a chance to set itself over a network. So even preventing them from changing the time won't guarantee accuracy.
What you could do is require a network connection to record values, so that you can verify the time on a server. If you must allow it to work without a net connection, you could at least always log the current time when the app is brought up and note if the time ever seems to go backwards. You'll know something is up if the timestamp suddenly is earlier than the previous timestamp. You could also do this check perhaps only when they try to record a value. If they record a value that has a timestamp earlier than any previous recorded value, you could reject it, or log the event so that the person can be questioned about it at a later time.
This is also one of those cases where maybe you just have to trust the user not to do this, because there doesn't seem to be a perfect solution to this.

The first thing to note is that the user will always be able to forge messages to your server in order to create incorrect records.
But there are some useful things you can use to at least notice problems. Most of the time the best way to secure this kind of system is to focus on detection, and then publicly discipline anyone who has gone out of their way to circumvent policy. Strong locks are meaningless unless there's a cop who's eventually going to show up and stop you.
Of course you should first assume that any time mistakes are accidental. But just publicly "noticing" that someone's device seems to be "misbehaving" is often enough to make bad behaviors go away.
So what can you do? The first thing is to note the timestamps of things when they show up at the server. Timestamps should always move forward in time. So if you've already seen records from a device for Monday, you should not later receive records for the previous Sunday. The same should be true for your app. You can keep track of when you are terminated in NSUserDefaults (as well as posting this information to the server). You should not generally wake up in the past. If you do, complain to your server.
Watch for UIApplicationSignificantTimeChangeNotification. I believe you'll receive it if the time is manually changed (you'll receive it in several other cases as well, most of them benign). Watch for time moving significantly backwards. Complain to your server.
Pay attention to mach_absolute_time(). This is the time since the device was booted and is not otherwise modifiable by the user without jailbreaking. It's useful for distinguishing between reboots and other events. It's in a weird time unit, but it can be converted to human time as described in QA1398. If the mach time difference is more than an hour greater than the wall clock time, something is weird (DST changes can cause 1 hour). Complain to your sever.
All of these things could be benign. A human will need to investigate and make a decision.
None of these things will ensure that your records are correct if there is a dedicated and skilled attacker involved. As I said, a dedicated and skilled attacker could just send you fake messages. But these things, coupled with monitoring and disciplinary action, make it dangerous for insiders to even experiment with how to beat the system.

You cannot prevent the user from changing time.
Even the time of an Location is adjusted by Apple, and not a real GPS time.
You could look at mach kernel time, which is a relative time.
Compare that to the time when having last network connection.
But this all sounds not reliable.

Related

In iOS11, how to keep a background task running past 10 min?

My question involves keeping an app that monitors user interactions in the background, for example time spent in one or the app. The issue arises when you can not have a background process run for more than 10 min or violate Apple's sandbox restrictions. Since I am relatively new to the Apple API, and could not find a direct answer that didn't involve location services or VOIP (which are both interesting options, but my application will not be able to use either viably), I come to ask for options in which I can understand when another app opens, when it closes, when it fetches data, and when user holds phone in certain orientation (ie when people hold their phone at certain angles to read text and etc.) for certain amount of time.
The purpose of this analyzation is to predict an attention span for the user, so I need to be able to run in the background, as the user will not be using my app while it predicts attention span.
My thoughts on this are possibly accessing the system log, and somehow parse previous statements (I don't think sandbox will allow), but inevitably the iOS system will suspend my processes after some point unless I put a timer. There is also the option of having the system wake up my app via opportunistic fetching, but that won't be useful if I don't collect the data.
Keep in mind this is within IOS 11, so it is much more restrictive than previous iterations. I understand this may seem like a complex problem, but even a direction in which to head could be useful to me.
This solution might work, (not recommended since it drains the battery quicker).
Just update your current location, every 10 mins. It will reset the background thread timer.

Check if system time is auto or user set

I need to set up user proof time keeping in my current project. I have found a lot of different question around this, but none that seem to have the answer I am looking for. These are the questions i have looked at so far:
XCODE: How to get/verify ACCURATE timestamp from device
Is it possible to get the atomic clock timestamp from the iphone GPS?
How can I get the real time in iPhone, not the time set by user in Settings?
I have several options for getting a time from a server connection but I need to have an offline solution too.
1.
It seems that using CLLocation gets the same time as as the device clock. Is there away to get the actual GPS time?
2.
I know the system time settings are not a public API thus can't be changed. Is it possible to find out if the device has the auto time setting turned on? If the auto time is on then I can rely on the system time for my purposes and if it's off then record that so I know that the time recorded is not to be trusted?
Just wanted to post my solution, incase some one else has the same issue.
After much research i found that getting GPS time of time setting info was not possible.
This solution isn't perfect nor real time but works for my purpose.
I have implemented a time check using cloud time each time the app comes on line. When the device re-establishes a server connection to sync events created off line i have put a verification that takes the last object device time and the new object device time and calculates the elapsed time between the two. (using NSdates so that daylight savings is covered) then do the same with the last available server time and the most recent server time. I then compare the results and if they are not within my margin of error the events are marked as invalid.
Hope that makes sense and is helpful for others.

opening and closing streaming clients for specific durations

I'd like to infrequently open a Twitter streaming connection with TweetStream and listen for new statuses for about an hour.
How should I go about opening the connection, keeping it open for an hour, and then closing it gracefully?
Normally for background processes I would use Resque or Sidekiq, but from my understanding those are for completing tasks as quickly as possible, not chilling and keeping a connection open.
I thought about using a global variable like $twitter_client but that wouldn't horizontally scale.
I also thought about building a second application that runs on one box to handle this functionality, but that seems excessive if it can be integrated into the main app somehow.
To clarify, I have no trouble starting a process, capturing tweets, and using them appropriately. I'm just not sure what I should be starting. A new app? A daemon of some sort?
I've never encountered a problem like this, and am completely lost. Any direction would be much appreciated!
Although not a direct fix, this is what I would look at:
Time
You're working with time, so I'd look at what time-centric processes could be used to induce the connection for an hour
Specifically, I'd look at running a some sort of job on the server, which you could fire at specific times (programmatically if required), to open & close the connection. I only have experience with resque, but as you say, it's probably not up to the job. If I find any better solutions, I'll certainly update the answer
Storage
Once you've connected to TweetStream, you'll want to look at how you can capture the tweets for that time period. It seems a waste to create a data table just for the job, so I'd be inclined to use something like Redis to store the tweets that you need
This can then be used to output the tweets you need, allowing you to simulate storing / capturing them, but then delete them after the hour-window has passed
Delivery
I don't know what context you're using this feature in, so I'll just give you as generic process idea as possible
To display the tweets, I'd personally create some sort of record in the DB to show the time you're pinging TweetStream that day (if it changes; if it's constant, just set a constant in an initializer), and then just include some logic to try and get the tweets from Redis. If you're able to collect them, show them as you wish, else don't print anything
Hope that gives you a broader spectrum of ideas?

Can I Rely on the iOS Device Clock Being Correct?

I am working on an app that will sync data between users through a server that I control. Currently, I am recording the UTC time of changes on each device, which then helps determine which data is most recent - the data on the server or on the device.
Can I rely on the iPhone and iPad UTC time being accurate? If not, how else could I stamp updates that will still let me detect updates from various users and detect possible update collisions?
Absolutely you cannot rely on the iOS device clock being correct. The user can set them to whatever they like, and does not have to synchronize with a time server.
When doing a sync, you could begin the process by obtaining the device's view of the current time. If this differs from the server's view of the current time, you could then apply this offset to the timestamps of the changes that are being uploaded, to bring them onto 'server time'. Clearly this assumes that the device clock has not been changed during the period in which the changes have been made—that is, it ignores the possibility that some of the changes have the correct time, and some require the offset to be applied.
The safest option would be to keep track of this offset, and see whether it would make any difference in a sync conflict. In any case where it would make a difference, apply the offset, but in any case where it would not affect what was regarded as the latest data, use the unmodified timestamp from the device—so if the user recalls that it was "3:00pm" when they did something, they will still see that event timestamped with 3:00pm. If using any offset calculation, don't forget to ensure that no item should ever be moved forward in time relative to the server to the point that it is being claimed to have occurred in the future. :)
For your purposes, it is best to use a logical clock like http://en.wikipedia.org/wiki/Lamport_timestamps
Do not depend on time being accurate on multiple machines for the core algorithm in a distributed system.
The biggest problem (especially with something like occasionally connected devices), is they can be disconnected for a long time and make many changes. We're not talking about drift here, we're talking potentially about many edits over long periods of time not connected to a server without a reliable time on the device.
If you want an approximation to interleave operations in a system where its not critical (facebook app, not financial), the server could maintain an ever increasing changeId long with every change - sort of a journal of changes applied. Then when the device changes an entity, it records it and references the last changeId it knows about. Writing that entity revision back to the server will cause a new changeId to get logged but the entities revision maintains the changeId when it was written by the device (what determines where it interleaves in the history of the entities writes) and the new server changeId (used when other clients get all revisions since changedId x).
the device can then retrieve all changes since the last changedId it knew about and will get all the entities - it can order revisions when viewing the entities based on the changeId it knew about when it was written.
That means a device thats connected more consistently will win more on writes (interleaved) and devices more occassionally connected will lose more often. But, all revisions will be written - just the latest wins. You could do that at a field or entity level. If at a field level, field changes by different users would effortlessly merge - if that's what you want.
It's an approximate interleaving of distributed revisions which simply interleaves based on your last message with the server.

I'm making a multiplayer game and I need to verify that players aren't speed hacking

For security reasons I have a feeling that that testing should be done server side. Nonetheless, that would be rather taxing on the server, right? Given the gear and buffs a player is wearing they will have a higher movement speed, so each time they move I would need to calculate that new constant and see if their movement is legitimate (using TCP so don't need to worry about lost, unordered packets). I realize I could instead just save the last movement speed and only recalculate it if they've changed something affecting their speed, but even then that's another check.
Another idea I had is that the server randomly picks data that the client is sending it and verifies it and gives each client a trust rating. A low enough trust rating would mean every message from the client would be inspected and all of their actions would be logged in a more verbose manner. I would then know they're hacking by inspecting the logs and could ban/suspend them as well as undo any benefits they may have spread around through hacking.
Any advice is appreciated, thank you.
Edit: I just realized there's also the case where a hacker could send tiny movements (within the capability of their regular speed) in a very high succession. Each individual movement alone would be legite, but the cumulative effect would be speed hacking. What are some ways around this?
The standard way to deal with this problem is to have the server calculate all movement. The only thing that the clients should send to the server are commands, e.g. "move left" and the server should then calculate how fast the player moves etc., then finally send the updated position back to the client.
If you leave any calculation at all on the client, the chances are that sooner or later someone will find a way to cheat.
[...] testing should be done server side. Nonetheless, that would be rather taxing on the server, right?
Nope. This is the way to do it. It's the only way to do it. All talk of checking trust or whatever is inherently flawed, one way or another.
If you're letting the player send positions:
Check where someone claims they are.
Compare that to where they were a short while ago. Allow a tiny bit of deviation to account for network lag.
If they're moving too quickly, reposition them somewhere more reasonable. Small errors may be due to long periods of lag, so clients should use interpolation to smooth out these corrections.
If they're moving far too quickly, disconnect them. And check for bugs in your code.
Don't forget to handle legitimate traversals over long distance, eg. teleports.
The way around this is that all action is done on the server. Never trust any information that comes from the client. If anybody actually plays your game, somebody will reverse-engineer the communication to the server and figure out how to take advantage of it.
You can't assign a random trust rating, because cautious cheaters will cheat only when they really need to. That gives them a considerable advantage with a low chance of being spotted cheating.
And, yes, this means you can't get by with a low-grade server, but there's really no other method of preventing client-side cheating.
If you are developing in a language that has access to Windows API function calls, I have found from my own studies in speed hacking, that you can easily identify a speed hacker by calling two functions and comparing results.
TimeGetTime
and...
GetTickCount
Both functions will return the number of seconds since the system started. However, TimeGetTime is much more accurate than GetTickCount, whereas TimeGetTime is accurate up to ~1ms vs. GetTickCount, which is accurate at around ~50ms
Even though there is a small lag between these two functions, if you turn on a speed hacking application (pick your poison), you should see a very large difference between the two result sets, sometimes even up to a couple of seconds. The difference is very noticable.
Write a simple application that returns the GetTickCount and TimeGetTime results, without the speed hacking application running, and leave it running. Compare the results and display the difference -- you should see a very small difference between the two. Then, with your application still running, turn on the speed hacking application and you will see the very large difference in the two result sets.
The trick is figuring out what threshold will constitue suspicious activity.

Resources