0%

CVE-2026-20643漏洞分析(瞎猜)

0x00 背景

前两天苹果通过全新的“后台安全改进”功能推送了一个webkit漏洞的补丁CVE-2026-20643,漏洞描述:

A cross-origin issue in the Navigation API was addressed with improved input validation.

WebKit Bugzilla: 306050

CVE-2026-20643: Thomas Espach

既然是webkit,那岂不是可以去GitHub commit记录里捞补丁了,于是就去webkit的commit记录里找(瞎猜)了一下。

0x01 关于Navigation API

简单来说,Navigation API 是 Web 平台为了解决 单页应用(SPA)路由管理 痛点而推出的“现代版”浏览器历史记录与导航管理接口。

在它出现之前,我们一直在忍受复杂的 window.historypopstate 事件。到了 2026 年,Navigation API 已经正式成为主流浏览器的“基准特性”(Baseline),彻底改变了前端路由的写法。

其中,chrome最早支持,大概在2022年,而safari和Firefox分别是2026年初和2025年底正式提供了支持,版本号如下:

image.png

来源:https://developer.mozilla.org/en-US/docs/Web/API/Navigation#browser_compatibility

0x02 漏洞分析

既然是Navigation API,同时又提到了cross-origin issue,那搜索的目标大概就能围绕navigation/canIntercept之类的关键词了,大概搜了一下GitHub,就发现了这个commit记录:

NavigationEvent#canIntercept is true when navigating to a different port

意思是canIntercept的实现没有严格按照whatwg文档的描述:

If targetURL and documentURL differ in their schemeusernamepasswordhost, or port components, then return false.

相同域名不同端口的地址canIntercept也返回了true,从而导致了像从localhost:3000localhost:3001 这样不同端口的跳转event也可以被Navigation API拦截,符合公告里的cross-origin描述。

修改的代码是Source/WebCore/page/Navigation.cpp ,增加了对上面几个参数的验证:

1
2
3
4
5
6
7
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#can-have-its-url-rewritten
if (documentURL.protocol() != targetURL.protocol()
|| documentURL.user() != targetURL.user()
|| documentURL.password() != targetURL.password()
|| documentURL.host() != targetURL.host()
|| documentURL.port() != targetURL.port())
return false;

同时commit记录里也给了测试用例navigate-event-canintercept-cross-port.html‎,直接把html和js依赖下载放到本地server,用safari打开页面测试就行了。

试了下已打了补丁的iPhone打开的结果:

IMG_4518.png

没打补丁的:

IMG_0004.png

做了一个去除测试框架js的精简版验证poc,这样看起来更直观一点:

https://www.flvin.com/CVE-2026-20643/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<meta charset="utf-8">
<title>Navigation API: canIntercept should be false for cross-port navigations</title>
<body>

<!-- log area -->
<div id="log"></div>

<script>

let log = function(...args) {
let originalLog = console.log;
originalLog.apply(console, args);
const logdiv = document.getElementById('log');
logdiv.innerHTML += `<p>${args.join(' ')}</p>`;
};

const currentPort = location.port || (location.protocol === 'https:' ? '443' : '80');
const otherPort = currentPort === '8800' ? '8000' : '8800';
const targetURL = `${location.protocol}//${location.hostname}:${otherPort}/`;


navigation.addEventListener("navigate", (event) => {
// Cross-port navigation should have canIntercept === false
log(`event.canIntercept: ${event.canIntercept}`);

const url = new URL(event.destination.url);
log(`Navigating to: ${url.href} (port: ${url.port})`);

if (event.canIntercept !== false) {
log(`canIntercept should be false when navigating from port ${currentPort} to port ${otherPort}`);

}

// Prevent the actual navigation
event.preventDefault();

});


// Trigger the cross-port navigation
const anchor = document.createElement('a');
anchor.href = targetURL;
document.body.appendChild(anchor);
anchor.click();


</script>
</body>
</html>

如果页面和console里显示event.canIntercept: true说明存在漏洞。

0x03 后记

打补丁的方式参照苹果的文档:https://support.apple.com/zh-cn/102657

如果没有自动安装可以手动选择安装。

今天突然想起去GitHub上搜一下这个CVE,然后发现苹果刚发补丁的那天就有大佬靠逆向扒出补丁了orz:https://github.com/zeroxjf/WebKit-NavigationAPI-SOP-Bypass

image.png

看来猜对了。