T09 · Insecure Skill Coding Practices
- Location
scripts/true_time.mjs:467- Finding
Unauthenticated NTP Responses Can Manipulate Time-Sensitive Calculations
- Content
View full analysis
{ const socket = dgram.createSocket("udp4"); const packet = Buffer.alloc(48); packet[0] = 0x1b; let settled = false; const finalize = (fn, value) => { if (settled) return; settled = true; clearTimeout(timer); try { socket.close(); } catch { // ignore close errors } fn(value); }; const timer = setTimeout( () => finalize(reject, new Error(`timeout after ${timeoutMs}ms`)), timeoutMs, ); socket.once("error", (error) => finalize(reject, error)); socket.once("message", (message) => { if (!message || message.length < 48) { finalize(reject, new Error("invalid NTP response (too short)")); return; } const seconds1900 = message.readUInt32BE(40); const fraction = message.readUInt32BE(44); const unixSeconds = seconds1900 - 2208988800; const ms = unixSeconds * 1000 + Math.round((fraction * 1000) / 0x1_0000_0000); finalize(resolve, { nowMs: ms, server }); }); socket.send(packet, 0, packet.length, 123, server, (error) => { if (error) { finalize(reject, error); } }); }); } ``` ### Technical Analysis The optional NTP implementation communicates over unauthenticated UDP and accepts the first packet received by the socket if it is at least 48 bytes long. The response is not adequately bound to the request or validated as a legitimate NTP server response. In particular, the implementation does not verify: - The source address and source port of the response. - The NTP mode, version, stratum, or leap indicator. - The response's originate timestamp against a r ...[truncated 2626 chars]- Remediation
View remediation
