在过去的几个月里,我们的 Windows Server 2022 机器中有几次会在事件日志中显示类似这样的警告
时间服务已将时间设置为偏移量 19630688 秒。,
然后时间就会向前跳转那么多秒。几分钟后,它似乎再次与时间服务器同步,我们收到以下错误
时间服务检测到系统时间需要更改 -19630688 秒。时间服务不会将系统时间更改超过 54000 秒。请验证您的时间和时区是否正确,以及时间源 time.nist.gov (ntp.m|0x0|0.0.0.0:123->128.138.140.44:123) 是否正常工作。
在出现一些类似于措辞的错误后,时钟通常会在大约 10 分钟内自行纠正。该框不在域中,并且它使用 Windows 中的默认时间服务器。知道这里可能出了什么问题吗?
答案1
更新:Ars Technica 已就此有问题的功能撰写了一篇文章:https://arstechnica.com/security/2023/08/windows-feature-that-resets-system-clocks-based-on-random-data-is-wreaking-havoc/
TL;DR:我们发现了最可能的根本原因:W32time 安全时间播种,它查看 SSL 握手标头中的旧“时间”值(该值在较新的 SSL 实现中是随机的),将其解释为正确的时间,并相应地设置时钟。
可以通过设置 UtilizeSSLTimeData 注册表项来关闭它:
reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w32time\Config /v UtilizeSslTimeData /t REG_DWORD /d 0 /f
并且可以指示 w3tm 重新读取其配置:W32tm.exe /config /update
较长的答案...
微软于 2015 年 11 月推出了一项名为“安全时间播种”的功能,该功能包含在 Windows Server 2016+ 中并默认启用。
它试图缓解系统没有电源来驱动系统时钟(例如电源故障和 CMOS 电池损坏)并因此在启动时出现完全错误的时间,无法安全地与其他来源通信以可靠地获取正确的时间的问题。
在传出 SSL 握手期间,它会查看“ServerUnixTime”(可能
gmt_unix_time
在规范中)。
TLS 1.2 规范规定如下(重点是我的):
根据发送者的内部时钟,当前时间和日期采用标准 UNIX 32 位格式(自 1970 年 1 月 1 日午夜以来的秒数,UTC,忽略闰秒)。 时钟无需正确设置由基本 TLS 协议定义;更高级别或应用协议可以定义其他要求。请注意,由于历史原因,数据元素使用 GMT 命名,GMT 是当前全球时间基准 UTC 的前身。
微软的初始博客在其帖子中说了以下内容(重点是我的):
ServerUnixTime 应该是服务器上的当前系统时间,但某些 SSL 实现也可以将其设置为随机值。我们观察到大多数服务器在此字段提供相当准确的值其余的提供随机值。我们使用该数据字段假设它有一定的准确性但也可能是错误的。
这表明他们误解了规范,他们的实现是在错误的假设下设计和运行的。当世界仍在使用较旧且较不安全的实现时,他们的实现可能运行良好,但随着越来越多的服务器进行更新,前提是完全错误的。
至少他们不信任单一来源,但由于提供时间的来源较少,而使用随机值的来源较多,因此 4 个字节相似到足以混淆他们的算法可能只是时间问题。
我们采取的方法是,不信任来自单个服务器的数据,无论该服务器的身份如何。我们依靠来自多个服务器的相互印证的信息来得出关于当前时间的共同事实。
他们进一步描述说,他们正在使用统计方法来查看何时可以将随机字节解释为正确的时间(重点是我的):
ServerUnixTime 和 OCSP 有效期的信息被合并以产生最小可能的可靠时间范围值以及置信度分数。当置信度分数足够高时,这些数据就变成了信息。
该gmt_unix_time
字段于 2013 年 9 月在 TLS 邮件列表中被讨论,比微软发布该功能早了两年,并于 2013 年 10 月在 OpenSSL 中实现,并于 2014 年 1 月发布。
commit 2016265dfbab162ec30718b5e7480add42598158
Author: Nick Mathewson <[email protected]>
Date: Sun Oct 20 15:03:24 2013 -0700
Do not include a timestamp in the Client/ServerHello Random field.
Instead, send random bytes, unless SSL_SEND_{CLIENT,SERVER}RANDOM_MODE
is set.
This is a forward-port of commits:
4af793036f6ef4f0a1078e5d7155426a98d50e37
f4c93b46edb51da71f09eda99e83eaf193a33c08
3da721dac9382c48812c8eba455528fd59af2eef
2583270191a8b27eed303c03ece1da97b9b69fd3
While the gmt_unix_time record was added in an ostensible attempt to
mitigate the dangers of a bad RNG, its presence leaks the host's view
of the current time in the clear. This minor leak can help
fingerprint TLS instances across networks and protocols... and what's
worse, it's doubtful that the gmt_unix_time record does any good at
all for its intended purpose, since:
* It's quite possible to open two TLS connections in one second.
* If the PRNG output is prone to repeat itself, ephemeral
handshakes (and who knows what else besides) are broken.
commit 2927791d77ddaef687e92b1779e0bff89bdc279f
Author: Nick Mathewson <[email protected]>
Date: Sun Oct 20 15:08:58 2013 -0700
Fix another gmt_unix_time case in server_random
### Major changes between OpenSSL 1.0.1e and OpenSSL 1.0.1f [6 Jan 2014]
* Don't include gmt_unix_time in TLS server and client random values
* (.. unrelated changes ..)
u/zanatwo 于 2017 年 3 月发现了这个问题并在 r/sysadmin 上报告,但没有迹象表明微软知道这个问题,因为它仍然处于启用状态。
它于 2022 年 1 月被 u/Thranx 重新发现,并在 r/sysadmin 上报告。
今年年初 @chris1out 在 ServerFault 上再次发文。
正如我们和其他人所经历的那样,这个问题出现的频率越来越高,可能是因为报告实际时间的服务器越来越少,而且只是报告随机值。这种情况很可能会继续增加,影响到更多的用户。
系统时钟是系统中最重要的共享可变状态,将时间更改为完全不同值的错误会破坏所有系统,其影响远远超出发生这种情况的单个服务器。毫无疑问,这是我遇到过的最严重的错误/缺陷,微软需要尽快禁用它。
与微软取得联系很困难,因此如果您遇到同样的问题,请向微软报告此问题。
非常感谢@test-is-prod 分享他们的发现并向我指出/u/zanatwo 的 Reddit 帖子!
参考:
- 安全时间播种 - 改善 Windows 中的计时(微软博客)
- Windows Server 2016 的时间准确性改进(Windows Server 文档)
- TLS 1.2 规范
- [TLS] 让我们从 TLS 中删除 gmt_unix_time(TLS 邮件列表)
- Windows 10 上的系统时间回跳。由名为“安全时间”的功能引起。(r/sysadmin 上的 u/zanatwo)
- Windows 时间有问题?有关 Windows 安全时间播种的 PSA (u/Thranx on r/sysadmin)
- Windows Server 2022 时间服务迈向未来(ServerFault 上的@chris1out)
答案2
我们的一些服务器也遇到了同样的问题。2019 年和 2016 年的混合服务器。物理服务器和虚拟机都有。我查看了几天的日志,但找不到任何比较。我向 MS 开具了一张票据,但到目前为止,还没有任何有价值的信息可以找出导致问题的确切原因。
您可以尝试运行它并看看是否有帮助:
net stop w32time
w32tm /unregister
w32tm /register
net start w32time
w32tm /resync /nowait
w32tm /resync /rediscover