Time is an important factor in many applications.
By employing timers or by using a date snapshot directly, a developer can do all kinds of useful things, like animations, controlled interactivity, timeouts, performance monitoring, benchmarking, or to provide a set of boundaries or localization customization.
Date object utilizes the operating system's internal clock settings or the local date system. The time and date systems are great for a lot of things as we mentioned above.
But using dates and timers also have some flaws.
The most notable flaw with the browser date system is the fact that it runs off the computer operating system state. This may or may not be considered a flaw, because most programming languages require some form of date and have to rely on the internal system.
To see what I mean, let’s look at some case studies where some browser applications are compromised due to a timer or date manipulation.
Preface: While these are not specifically security exploits, I still consider them vulnerabilities and exploits of an application. Therefore, identifiable details and names of the websites have been changed to protect the privacy and security of the applications that have these issues. I have notified the developers of the applications in order to help them become aware of and/or fix these issues.
Case Study One
A local government website.
When you get a ticket, there is the occasional option to take traffic school online. While attending the class in your browser, you follow along through some pages with reading material, and then take a test at the end. Simple enough.
This browser application has been designed from the ground up with a visible timer on each page. It requires you to sit on a page for 20 minutes to an hour in order for you to read the whole page. Incidentally, this feature is also there to prevent people from just skipping through the content. This acts as a way to penalize them, after all, it is traffic school.
Unfortunately for this application, the browser console easily exposes a view inside the code, and the code exposes a way for the browser console to modify the internals of the program.
In this case, someone can open up the console, modify the running timer to have it finish early and set the page timer to zero, allowing the user to skip ahead.
This is terrible because a user with this exploit can decide that they want a shorter version of traffic court, creating inequality between those that can take traffic school online and those that go to the courthouse for traffic school.
Case Study Two
A browser video game.
In this game, there are multiple players that can play at the same time. They are not playing simultaneously, but their high scores are linked together and the highest one will win the round. The winner can eventually move on to a round where they win a prize.
The high score is determined by a number of different statistics that I cannot clearly see from the browser, but there is one fatal issue: A sizable portion of the high score is from the amount of time the player is “alive” in the round.
As a developer, you would think:
How would I compute the high score? Probably just spin up a timer and calculate it at the end.
Since the game can run for a very long time, up to 45 minutes per round, the developer here opted not to use a timer but instead used the difference of two timestamps in seconds.
What that means is, they take a snapshot of the current start time and store in a formatted Date String, and then once the game is over, they do another snapshot for the current end time and compute a difference in seconds.
Now, it seems “genius” in a way because of less overhead devoted to timers, which gives more computing time to the browser (which is arguable). But the downside of this is the exploit that I found.
Start the game, then simply change your system clock to sometime in the future and keep playing. Your score will build as you play, but you also obtain a sweet bonus boost in points from the time diff.
Pretend I set my clock to a year in the future, trigger a game over and score a gigantic million point high score in the game. Obviously, someone wouldn’t want to be too suspicious, so instead, they opt for an hour, to provide just enough boost in points to avoid skepticism.
Fortunately, at least at time of writing, I don’t think anybody was aware of the bug except for myself. And I don’t cheat at video games, I take losses and move on.
Case Study Three
The final countdown — a concert ticket sale page.
Countdown pages are a flashy animated way to prevent the user from accessing content or a page until a certain date passes. You’ve seen them all around, they basically just have giant numbers that say something like:
0 days, 23 hours, 43 minutes, 10 seconds
And countdown with some fancy animation. The page is unlocked or published when the timer completes.
You would think that these check with the server in some way to prevent a premature launch. And usually, they do. But in the case of single-page applications, sometimes developers get lazy.
They don’t ask the server what time it really is. They just assume the browser is trustworthy.
Similar to the previous issue, the developer chose to find the difference between two Dates. In this instance, they used UTC timestamps for both, which seems like a logical and reasonable idea — no matter where the user is, they will still have to wait for the same countdown with the same amount of time left over.
What was not accounted for: when a user visited their page.
Suppose there are 300 seconds (5min) left until this countdown timer finishes. As expected, many users load up the page in order to get their spot in “line” to purchase a much-wanted item, in this case, concert tickets.
In this app, they let the browser tell them what time it is. And 99% of the time this is probably just fine.
As a matter of fact, I myself found this by accident, because I was testing an application’s date formatting, and had my clock wrong. When I loaded the page, I had no countdown clock. Had they started early? Did I miss my chance?
Out of curiosity, I loaded up the website on my phone and could confirm that the clock was still there. I soon realized my system clock was set to the end of the month, far past the countdown termination date.
Because of this failure to check the Date properly, and no server-side validation, I was able to get my tickets early, albeit just by a few minutes. Needless to say, the concert didn’t sell out until a few days later anyways, but still an interesting bug.
Who knows how early the server would have allowed ticket purchases, and who knows if anyone on their team would even notice.
With these three case studies in mind, what have we learned?
One, we can trust that the browser is great for finding a user’s time zone, and we can use that information to format dates and time to localize them.
Two, we also understand that using a timer in the browser can be safe, but should be handled cautiously, being careful to avoid global variables that expose any timers that can affect the application’s boundaries, such as timed waiting periods, and perhaps having some tamper-proofing server side.
Finally, we can use the date object for simple subtraction as long as it only affects the user. When it comes to things like competitive games or purchasing queues, simple subtraction of browser-supplied dates from time A to time B is problematic.
Bottom line: In the above events, a date or timer bug allowed a user to run the applications in an unexpected way.
These could lead to more severe vulnerabilities in your application.
When handling time, be aware of these ideas. Always provide the actual time from a trusted source in UTC format — the browser can understand it, and can parse it into a Date object.
It’s not perfect, but programming with time is never perfect.