Skip to main content

Traceability loss - Server's clock

Need

Ensuring accurate time synchronization with NTP servers

Context

  • Usage of C# for building robust and scalable applications
  • Usage of the System library for low-level operating system interactions

Description

Non compliant code

using System;

namespace VulnerableApp
{
public class ServerTime
{
public DateTime GetCurrentTime()
{
return DateTime.Now;
}
}
}

The above code represents a simple ASP.NET Core backend application where there is a class ServerTime that has a method GetCurrentTime() which returns the current system time using DateTime.Now.

The vulnerability here is due to the fact that the system's internal clock is not synced with any NTP (Network Time Protocol) servers. The DateTime.Now property in C# gets the current date and time from the system's clock. If the system's clock is not accurate, then this method will return inaccurate results.

This could lead to a traceability loss vulnerability, as it could cause inconsistencies and inaccuracies in logging, timestamps, and other time-sensitive operations in the application. For example, if the system's clock is ahead or behind the actual time, it could cause issues like prematurely expiring sessions or tokens, inaccurate timestamps in logs, and other potential issues.

In a distributed system, this could also lead to inconsistencies between different servers or components if they are not all synced to the same time source. This could cause issues with operations that depend on the order of events or the exact time an event occurred.

This vulnerability could be exploited by an attacker to cause confusion, hide their activities, or exploit time-based vulnerabilities in the system. For example, if an attacker can manipulate the system's clock, they could potentially extend the lifetime of a session or token, or cause other time-related security controls to fail.

Steps

  • Implement NTP (Network Time Protocol) synchronization to sync the server's clock with reliable time sources.
  • Configure the application to use the synchronized server time instead of the local system time.
  • Ensure that the NTP synchronization is performed periodically to keep the server's clock accurate.
  • Handle any potential errors or exceptions that may occur during the NTP synchronization process.

Compliant code

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace VulnerableApp
{
public class ServerTime
{
private const string NtpServer = "pool.ntp.org";

public async Task<DateTime> GetCurrentTime()
{
try
{
var ntpData = new byte[48];
ntpData[0] = 0x1B; //LeapIndicator = 0 (no warning), VersionNum = 3 (IPv4 only), Mode = 3 (Client Mode)

var addresses = Dns.GetHostEntry(NtpServer).AddressList;
var ipEndPoint = new IPEndPoint(addresses[0], 123);
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

await socket.SendToAsync(ntpData, SocketFlags.None, ipEndPoint).ConfigureAwait(false);
await socket.ReceiveAsync(ntpData, SocketFlags.None).ConfigureAwait(false);

ulong intPart = BitConverter.ToUInt32(ntpData, 40);
ulong fractPart = BitConverter.ToUInt32(ntpData, 44);

intPart = SwapEndianness(intPart);
fractPart = SwapEndianness(fractPart);

var milliseconds = intPart * 1000 + (fractPart * 1000) / 0x100000000L;
var networkDateTime = (new DateTime(1900, 1, 1)).AddMilliseconds((long)milliseconds);

return networkDateTime;
}
catch (Exception ex)
{
// Handle exception here
throw new Exception("Error occurred while getting server time", ex);
}
}

private static uint SwapEndianness(ulong x)
{
return (uint)(((x & 0x000000ff) << 24) +
((x & 0x0000ff00) << 8) +
((x & 0x00ff0000) >> 8) +
((x & 0xff000000) >> 24));
}
}
}

The above code fixes the vulnerability by implementing NTP synchronization. The GetCurrentTime method now fetches the current time from an NTP server instead of using the local system time.

The NtpServer constant is set to "pool.ntp.org", which is a round-robin of NTP servers. The method sends a request to the NTP server and receives the server time in response. The response is then converted to a DateTime object.

The SwapEndianness method is used to convert the time from big-endian format (used by NTP) to little-endian format (used by .NET).

The method is now asynchronous and uses the async/await keywords to handle the network operations without blocking the main thread.

In case of any errors during the NTP synchronization process, an exception is thrown. This exception should be caught and handled appropriately in the calling code.

References