0

I am working on a parental control Windows desktop application. A lot of actions/events depend on the correct system time. The problem is that I cant trust the system time because it can be changed. So whenever possible I want to somehow get the time from the internet. The time should be in UTC because I want it to work in different time zones. The solution doesnt have to be bulletproof. I know for sure that the kids will always find the way around it ;-) I want at least something that cant be tricked with two mouse clicks.

Currently I am considering these options to get the time:

  • from the public NTP server. But I am afraid that the server might go down in the future.
  • from the WebClient response header from a website like google.com I think that the response time is not in UTC and I am afraid that the web server might block the requests if they are too frequent.
  • get a server UTC time from my own web server API. I think that this might be currently my best option.

It would also be great if I would be able to cache the time so that I would not have to sync it too often. I dont want to spam the time servers with requests every second.

For the caching part I was thinking something like storing the DateTime from the internet and system DateTime of the last synchronization. And computing the time based on these values.

What do you think is the best approach for getting and caching the correct UTC time from the internet?

Thanks a lot for your suggestions.

VertexLooper
  • 17
  • 1
  • 4
  • Pick a [stratum 2 time server near you](http://support.ntp.org/bin/view/Servers/StratumTwoTimeServers) and a backup (and yes it's considerate not to be syncing too often). If they go down, you'll have bigger problems -- like foraging for food. – 15ee8f99-57ff-4f92-890c-b56153 Jul 29 '19 at 15:43
  • Thanks I will check it out. And good joke. :-) – VertexLooper Jul 29 '19 at 15:49
  • You can subscribe to the [SystemEvents.TimeChanged](https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.systemevents.timechanged) (it's triggered when a User modifies the current time). If the event is raised, check the current time via API and correct if necessary. – Jimi Jul 29 '19 at 16:16
  • Be aware that the `SystemEvents.TimeChanged` event recommended by @Jimi tends to fire twice for anything that triggers it (actual user initiated time changed, changing "Set time automatically"). – TnTinMn Jul 29 '19 at 16:25
  • @TnTinMn Yes, that's true. You'll get the notification twice. But it's easily circumvented with a StopWatch. If you make the event handler `async`, you can add a `[StopWatch].IsRunning` check on top, raise a custom notification, `await Task.Delay(200).ConfigureAwait(false)` (or more) and then stop the watch. The current Time can also be extract from the Headers of `www.google.com`. It's very precise. – Jimi Jul 29 '19 at 17:50
  • @jimi, well that is definitely one of the more convoluted methods I've heard of for dealing with the issue. Points for creativity though. – TnTinMn Jul 29 '19 at 18:05
  • @TnTinMn Why? It's 4 lines of code to get rid of double notifications (when you're dealing with actual doppelgangers). The *raise a custom notification* part infers that the System event is meant to be handled by a specialized class which then distributes the notifications to the subscribers of its custom event. Unless you want to override WndProc. What are you suggesting? – Jimi Jul 29 '19 at 18:19
  • @TnTinMn [Here's a PasteBin](https://pastebin.com/bXRz0aQJ) of what I meant (well, I wrote it in 2 minutes, so... consider that). – Jimi Jul 29 '19 at 18:35
  • I don't understand why you want to bother with this. On Windows (and I think, other OS as well), you need admin privileges to change the clock. A person who has admin privileges is just going to disable your software instead of wasting time messing with the clock. – Peter Duniho Jul 29 '19 at 19:14

3 Answers3

1

You can use free time API service to get real utc time. For example: "https://worldtimeapi.org/api/timezone/Europe". This API endpoint supports SSL, but it is still not secure, and responses can be altered by, for example, using fiddler proxy and changing trusted root certificate list on local machine. In order to prevent response tampering you can check https://worldtimeapi.org certificate hash manually:

 var req = WebRequest.CreateHttp("https://worldtimeapi.org/api/timezone/Europe");
 req.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => certificate.GetCertHashString() == "<real_Hash_here>";
 var response = req.GetResponse();
 ///parse json response here

To get hash of certificate you should can you navigate to target API website (https://worldtimeapi.org/api/timezone/Europe) with browser, download (export) certificate and use some SSL tool like OpenSSl to get hash.

I believe that only way of tricking such time check is to reverse engineer code. Some obfuscation tool will further increase security.

P.S: instead of manual certificate hash check. You can also set Proxy property of HttpWebRequest to null. this will hide you request from network debugging proxy like fiddler or charles. This is easier to implement, but less secure way, because attacker still has a way to inspect you request

Dzliera
  • 646
  • 5
  • 15
0

It is easy enough to limit a Windows user from changing the clock. At that point the attacker would have to do stuff like changing it in the BIOS/UEFI. But if the attacker has that level of access, nothing your puny user code can do can truly stop them.

The place in the internet to ask "What time is it?", are the NTP servers. Indeed those are the guys Windows asks. And propably your Mobile Phone Provider too.

Internatlly the computer should be storing UTC. That dispalyed clock you see in the lower right corner? Or what DateTime.ToString() gives you? That is just a interpretation of the UTC values based on the Culture and Timezone Settings of the Windows user. It has about much say as any other string.

Christopher
  • 9,634
  • 2
  • 17
  • 31
  • Thanks. Limit the user from changing the clock is a good idea. Do you know by any chance how? Is there any Windows API for that? Or do I need to change something in the registry? I will also look more into the NTP servers. – VertexLooper Jul 29 '19 at 15:52
  • @VertexLooper I am not sure there is a convenient way to set those values. I guess "easy" might have been a very wrong term here. It is at best relatively easy if you got some admin experience. For your programm you will have to track down register values: https://stackoverflow.com/questions/1789434/changing-local-security-policy-programmatically Also your programm propably has to run as Adminsitrator to make such a change. Looking at it, just asking for the NTP time might be easier. Of course it is questionable how much your application can do anyway. After all it is "only user code" too. – Christopher Jul 29 '19 at 16:41
-1

Just simply use:

DateTime utcDate = DateTime.UtcNow;
Catarina Ferreira
  • 1,824
  • 5
  • 17
  • 26
  • Thanks for your reply. I can use that and I am using that. Problem is that when the user changes the system time this also changes and it gives wrong values. Thats why I want to get the current UTC time from the internet. – VertexLooper Jul 29 '19 at 16:09
  • Try this solution instead: https://stackoverflow.com/questions/6435099/how-to-get-datetime-from-the-internet – Catarina Ferreira Jul 29 '19 at 16:29