Skip to main content

Traceability loss - Server's clock

Need

Ensuring accurate time synchronization for the server's internal clock

Context

  • Usage of Scala for building scalable and high-performance applications
  • Usage of java.time for handling date and time in Java applications
  • Usage of play.api.mvc for handling HTTP requests and responses in Play Framework
  • Usage of play.api.libs.json for JSON parsing and manipulation in Play Framework

Description

Non compliant code

import java.time._
import play.api.mvc._
import play.api.libs.json._

class ServerTimeController extends Controller {
def getTime = Action {
val serverTime = LocalDateTime.now()
Ok(Json.obj("serverTime" -> serverTime.toString))
}
}

The above code represents a simple Scala/Play API endpoint that returns the current server time. The getTime function uses the LocalDateTime.now() function to get the current date and time from the server's system clock.

The vulnerability here is that the server's internal clock is not synchronized with an NTP (Network Time Protocol) server. This means that the time returned by this function may not be accurate.

In a real-world application, this could lead to a variety of problems. For example, if this function is used to timestamp events or transactions, those timestamps may not be correct. This could lead to issues with data integrity, auditing, and traceability.

Furthermore, if the server's clock is significantly out of sync, it could cause issues with session management, caching, and other time-sensitive functionality.

The server's clock should be regularly synchronized with an NTP server to ensure that it always has the correct time. This is typically done at the operating system level, rather than within the application itself. However, the application could also implement a check to ensure that the server's clock is synchronized.

Steps

  • Step 1: Synchronize the server's clock with NTP servers.
  • Step 2: Use a reliable time synchronization mechanism in the application.
  • Step 3: Update the vulnerable code to use the synchronized server time instead of the local system time.

Compliant code

import java.time._
import play.api.mvc._
import play.api.libs.json._
import org.apache.commons.net.ntp.TimeInfo
import org.apache.commons.net.ntp.NTPUDPClient
import java.net.InetAddress

class ServerTimeController extends Controller {
def getTime = Action {
val client = new NTPUDPClient()
val inetAddress = InetAddress.getByName("pool.ntp.org")
val timeInfo = client.getTime(inetAddress)
val returnTime = timeInfo.getMessage().getTransmitTimeStamp().getTime()
val serverTime = new LocalDateTime(returnTime)
Ok(Json.obj("serverTime" -> serverTime.toString))
}
}

The above code fixes the vulnerability by synchronizing the server's clock with NTP servers.

The NTPUDPClient class from the Apache Commons Net library is used to create a new NTP client. This client is then used to get the time from the NTP server at "pool.ntp.org". The getTime() method of the NTPUDPClient class returns a TimeInfo object, which contains the time information from the NTP server.

The getTransmitTimeStamp() method of the TimeInfo object is used to get the transmit timestamp from the NTP server. This timestamp is the time at which the NTP server sent the response to the client. The getTime() method of the TimeStamp class is used to get the time in milliseconds since January 1, 1970, 00:00:00 GMT.

The time in milliseconds is then used to create a new LocalDateTime object, which represents the current date and time according to the NTP server. This LocalDateTime object is then returned as the server time.

This way, the server's clock is synchronized with the NTP server, and the application uses the synchronized server time instead of the local system time. This fixes the traceability loss vulnerability due to the server's clock not being synced with NTP servers.

References