查看原文
其他

了不起的Chrome浏览器(5):Chrome 93支持Error Cause,我国首个ECMAScript提案可以用了

寒雁Talk 寒雁Talk 2022-09-08

8月31日正式发布的Chrome 93,带来了哪些有意思的新特性呢?


背景


十多年来,Web技术突飞猛进,其中Chrome功不可没,了解Chrome可以帮助我们理解整个行业的发展趋势。


因此,我将以《了不起的Chrome浏览器》为题,对Chrome的每一个版本的重要特性进行详细解读,同时分享一些自己的一些思考:



通过专注于Chrome的写作,既可以可以提高我的专业能力,也可以提高个人影响力。我的长期目标是在2025年出版一本关于Chrome的书,毕竟出版自己的书每一个写作者最高的追求。


我是寒雁,一个热爱写代码和写文章的程序员,欢迎关注我的微信公众号寒雁Talk


TL;TR


  • Chrome 93最大的亮点是什么?对于国内的小伙伴来说,最值得关注的特性莫过于Error Cause,这是我国首个进入Stage 3的ECMAScript提案,虽说这个特性本身很简单,但是其象征意义很大,将鼓励更多国内程序员参与国际技术标准的制定。

  • Chrome 93是哪天发布的?2021-08-31

  • Chrome 93更新了多少个特性?18个,具体有哪些特性可以查看Chrome Platform Status

  • Chrome 93将使用哪个版本的V8引擎?v9.3

  • 我感兴趣的新特性依次有哪些?

    • Error Cause

    • Object.hasOwn

    • Block ports 989 and 990

    • Remove 3DES in TLS

    • WebOTP API: cross-device support

    • Clipboard API: Svg


    详细解读


    Error Cause


    Chrome 93支持了Error Cause,支持在新建Error时配置cause参数,这样可以帮助我们更好的进行异常处理:


    try { return await fetch("//unintelligible-url-a") // 抛出一个 low level 错误 .catch((err) => { throw new Error("Download raw resource failed", { cause: err }); // 将 low level 错误包装成一个 high level、易懂的错误 });} catch (err) { console.log(err); // Error: Download raw resource failed console.log("Caused by", err.cause); // Caused by TypeError: Failed to fetch}


    Error Cause提案由阿里巴巴的昭朗同学负责,从去年9月份开始,到今年3月份进入Stage 3,再到现在Chrome支持,整个推进速度还是蛮快的。


    再次恭喜昭朗同学,这是我国首个进入Stage 3的EcmaScript提案!


    Error Cause提案本身很简单,但是它的价值还是蛮大的,社区类似的解决方案@netflix/nerror的周下载量高达10万。


    但是,如何在一个国际化的标准组织推动一个提案,可不是一件简单的事情,需要耗费不少的时间和精力。


    作为一个程序员,能够让编程语言变得更好,是一件挺有价值的事情,感兴趣的同学赶紧行动起来吧!


    Object.hasOwn


    Chrome 93新增了Object.hasOwn方法,用于判断Object是否存在某个属性:


    const obj = { name: "test" };console.log(Object.hasOwn(obj, "name")); //true


    不是有了Object.prototype.hasOwnProperty么?有啥区别?


    const obj = { name: "test" };
    // 直接调用console.log(obj.hasOwnProperty("name")); //true
    // 通过call方法调用console.log(Object.prototype.hasOwnProperty.call(obj, "name")); //true


    hasOwnProperty的函数名有点冗长,社区还有一个npm包has来解决这个问题,其周下载量高达2200万。hasOwn比hasOwnProperty更短,这会让它得到大家更加偏爱,不过这倒不是问题的关键。


    hasOwnProperty是通过propertype继承的方法,可以被重写,这会导致结果错误:

    let foo = { hasOwnProperty: function () { return false; }, bar: "Here be dragons",};
    foo.hasOwnProperty("bar"); // false


    ESLint的no-prototype-builtins规则就是为了避免这个问题,禁止调用Object.prototype所继承的方法。


    hasOwn是Object的静态方法,其实还是可以通过Object.defineProperty重写,这就有点尴尬了...


    Block ports 989 and 990


    为了防止ALPACA攻击,Chrome 93屏蔽了989和990端口,即FTPS协议所使用的端口


    ALPACA攻击由一些德国科学家所发现,今年6月份才公开,是一种非常巧妙地跨应用层网络协议的攻击方式,利用了同一个TLS证书被多个不同协议的服务复用的问题。


    ALPACA攻击的详细过程如下图:


    图片来源:ALPACA Attack


    • TLS协议既可以用于HTTP协议(或HTTPS),也可以用于FTP协议(或FTPS),它独立于应用层协议。

    • 同一个TLS证书可以被多个不同应用层协议的服务共用,比如,通配符证书*.bank.com可以同时用在HTTP服务(域名为www.bank.com)和FTP服务(域名为ftp.bank.com)。因此,当客户端本来与www.bank.com进行TLS连接时,如果返回的是ftp.bank.com服务拥有的通配符证书(wildcard certificate)*.bank.com,TLS连接也可以验证成功,因为本来用的就是同一个证书。

    • TLS可以对TCP包的内容进行加密,但是并不能对TCP包的IP和端口进行加密。中间人(Man in the Middle,简称为MitM或者MITM)确实没法破译或者篡改通信内容,但是它可以篡改IP和端口,将原本发送到www.bank.com的TCP包转发到ftp.bank.com。

    • 这样一来,用户本来是想访问HTTP服务(域名为www.bank.com),由中间人转发了一下,实际访问的是FTP服务(域名为ftp.bank.com)。用户浏览器发送的是HTTP请求,而FTP服务把请求内容当做FTP命令来解析;FTP服务返回的FTP协议的返回数据,用户浏览器把它当做HTTP返回数据来解析,这就是所谓的跨协议攻击。由于浏览器与FTP服务对跨协议攻击的防备不够,就会存在安全隐患。

    • 既然协议都不一样,是不是只会报错,没什么好担心的呢?事实并非如此。研究者发现有3种方式可以用于跨协议攻击,分别是Upload Attack、Download Attack、Reflection Attack,黑客可以通过这些攻击方式获取Cookie、在网页中执行任意的JavaScript代码(即存储型XSS和反射型XSS)。

    • 以最简单的Upload Attack为例,黑客可以诱使用户访问其网站www.attacker.com,进行CSRF攻击,发送跨域的POST请求到www.banck.com,这个请求实际上会被中间人转发到ftp.bank.com,如果www.bank.com没有使用same-site保护其Cookie,则用户的Cookie会被上传到ftp.bank.com,攻击完成。

    • 黑客所发送的POST请求是特殊定制的,内容中包含了FTP上传命令:

    <!-- 代码来源:https://github.com/RUB-NDS/alpaca-code/blob/master/testlab/servers/files/nginx-attacker/html/upload/ftps.html --><script> var formData = new FormData(); formData.append("a", "USER bob"); // FTP用户名 formData.append("b", "PASS 12345"); // FTP密码 formData.append("b", "TYPE I"); // 二进制模式 formData.append("c", "PASV"); // 被动模式 formData.append("d", "STOR leak"); // FTP上传命令
    var xhr = new XMLHttpRequest(); xhr.open("POST", "https://target.com"); xhr.send(formData);
    setTimeout(function() { window.location = "https://target.com"; }, 5000);</script>


    看起来挺可怕的,但是实际上还好,因为实施ALPACA Attack的前提条件挺多的,还是以Upload Attack为例:


    • 同一个TLS证书被多个服务共用,这个条件还是相对容易满足,因为运维同学为了省事嘛,我也干过运维,挺喜欢通配符证书的,可惜当时Let's Encrypt还不支持所以没用过,以后也不敢用了;

    • 黑客能够实施CSRF攻击,正确配置same-site就可以杜绝了;

    • 被攻击的HTTPS服务使用是HTTP/1.1及以下版本,因为较新的Chrome、Firefox、Edge浏览器只支持通过ALPN(Application-Layer Protocol Negotiation)建立HTTP/2连接,必须指定应用层协议,也就没法搞跨协议攻击了;

    • 黑客拥有FTP服务的账号密码,00后小朋友估计都没用过FTP这种古老的协议;

    • 黑客可以实施中间人攻击,这是最难的一点,需要入侵网络中的节点,内网稍微简单一点,内鬼要搞事就难办了啊;


    因为实施这一攻击的前提条件比较多,所以它更多的是一种理论上的攻击方式,不必过于担心。虽然说ALPACA Attack实际威胁不大,但是它所发现的问题还是很有价值的,它发现了看似牢不可破的TLS的隐藏漏洞:同一个证书被多个不同应用层协议共用以及不保护IP和端口。目前来看,预防ALPACA Attack最好的方式是不要跨协议共享TLS证书,同时启用ALPN。


    至今,Chrome已经累计屏蔽了13个端口,见下表:


    日期

    Chrome版本

    屏蔽端口

    2021-08-31

    Chrome 93

    989、990

    2021-05-25

    Chrome 91

    10080

    2021-04-14

    Chrome 90

    554

    2020-11-17

    Chrome 87

    5060、5061

    69、137、161、 1719、1720、1723、6566


    所以大家以后看到哪个端口不能再用了,不要感觉奇怪。道高一尺魔高一丈,目测被屏蔽的端口会越来越多。再这样搞下去,是不是只有443端口能用了?


    Remove 3DES in TLS


    为了预防Sweet32攻击和Lucky Thirteen攻击,Chrome 93移除了对TLS_RSA_WITH_3DES_EDE_CBC_SHA密码套件的支持。


    TLS_RSA_WITH_3DES_EDE_CBC_SHA密码套件的名字很长,其中3DES和CBC代表对称加密算法,它在2016年被证明可以被Sweet32攻击。


    我们不妨重点分析一下Sweet32攻击是怎么回事。


    3DES是对称加密算法( symmetric encryption),同时也是分块加密算法(block cipher)。它会将需要加密的文本切分为64比特的文本块,然后对每一块进行加密。


    由于3DES算法的分块长度只有64比特(更安全的AES算法的分块长度是128比特),因此它容易受到生日攻击(birthday attack)。


    生日攻击(birthday attack)的原理来源于生日悖论(birthday paradox):


    在不少于23 个人中,至少有两人生日相同的概率大于50%。例如在一个30 人的小学班级中,存在两人生日相同的概率为70%。对于60 人的大班,这种概率要大于99%。


    生日悖论并不是真正的悖论,通过简单的概率公式就能算出来,它只是违反了我们的直觉,因此被称为"悖论"。


    基于生日悖论,可以推导出(此处忽略推导过程...),只要收集足够多的3DES加密块,其中必定会出现完全相同的3DES加密块。


    另外,由于CBC加密算法可以被碰撞攻击(collision attack)。只要找到相同的3DES加密块,就可以根据部分已知明文通信内容恢复部分未知的加密通信内容比如Cookie(此处再次忽略推导过程...)。


    因此,黑客所要做的事情,就是发起CSRF攻击,重复发送大量HTTPS请求,JavaScript代码如下:

    // 代码来源:https://sweet32.info/var url = "https://10.0.0.1/index.html";var xhr = new XMLHttpRequest();
    // Expand URL to ~4kB using a query string// Alternatively, force a large cookieurl += "?";var x = 10000000;for (var i = 0; i <= 500; i++) { url += x++;}
    while (true) { xhr.open("HEAD", url, false); xhr.withCredentials = true; xhr.send(); xhr.abort();}


    然后,黑客进行抓包,并找到相互冲突的3DES加密块。找到足够多的冲突,就可以恢复Cookie了。


    WebOTP API: cross-device support


    Chrome 93更新了WebOTP API,支持跨设备。这里所谓的跨设备,指的是安卓端和PC端的Chrome浏览器。


    当你的安卓端和PC端的Chrome浏览器都登录了同一个Google账号,安卓手机收到短信验证码之后,不再需要在PC端手动输入了,在手机端直接提交即可:

    视频来源:Verify a phone number on desktop using WebOTP API


    WebOTP这个名字有点奇怪,其中OTP是one-time-passwords的缩写,指的就是手机的短信验证码。对于很多iOS和安卓APP,我们已经不再需要手动复制粘贴验证码了,APP可以自动识别和提取验证码,我们只需要轻点一下即可。WebOTP就是为了给Web应用带来相同的体验。


    如下图,Web应用可以通过navigator.credentials.get获取OTP,当收到短信验证码时,Chrome则可以自动匹配对应域名的OTP,用户确认之后则可以直接验证OTP,不再需要手动复制粘贴验证码,其流程如下图:


    图片来源:Verify phone numbers on the web with the WebOTP API


    WebOTP API是去年Chrome 84新增的,并且支持在跨域的iframe中使用:


    日期

    Chrome版本

    说明

    2021-08-31

    Chrome 93

    WebOTP API支持跨设备

    2021-05-25

    Chrome 91

    支持在跨域的iframe中使用WebOTP API

    2020-07-14

    Chrome 84

    新增WebOTP API,用于自动提取手机短信验证码


    Feature: Clipboard API: Svg


    Chrome 93更新了Clipboard API,支持SVG格式。这一特性,有望用于图片相关的应用(比如:Inkscape, Adobe Illustrator,Figma、Photopea)。


    Clipboard API可以用于剪贴板的读写,支持异步比同步接口document.execCommand的性能更好、基于permission API的权限控制更安全。


    Clipboard API是2018年Chrome 66新增,目前已经支持图片、HTML、文件等多种格式,功能越来越强大:


    日期

    Chrome版本

    说明

    2021-09-21

    Chrome 94

    Clipboard API支持从剪贴板读取保留metadata的原始PNG文件

    2021-08-31

    Chrome 93

    Clipboard API支持复制粘贴SVG

    2021-05-25

    Chrome 91

    Clipboard API支持从剪贴板读取只读文件

    2020-10-06

    Chrome 86

    Clipboard API支持复制粘贴HTML

    2020-08-25

    Chrome 85

    Clipboard API支持feature policy(即permission policy)

    2019-07-30

    Chrome 76

    Clipboard API支持复制粘贴图片

    2018-04-17

    Chrome 66

    新增异步Clipboard API



    总结


    本篇是《了不起的Chrome浏览器》的第5篇,凑满5篇就可以召唤神龙了?


    其实,我2年前还写过一个《JavaScript深入浅出》系列,不过后来因为工作的巨大变动(详见:从创业者到打工人,我在阿里这1年)放弃了:



    所以,当我开始写《了不起的Chrome浏览器》时,我也挺担心自己会再次放弃,现在写到第5篇,这样的担心越来越少了:


    • Chrome每个月更新一个版本,每个月写一篇博客,这个写作节奏不紧不慢;

    • Chrome的文档、博客质量非常高,所以我不用担心没有内容可以写,这为我省去了一半的时间;

    • 作为一个写了6年博客的老司机,写博客对我来说挺简单的,也很喜欢;

    • 每篇博客至少要花10个小时,80%的时间是在看博客、论文、视频等参考资料,每次都能学到一些新的知识点;

    • Flag已经立了,2025年要出版一本关于Chrome的书,那就得做到啊;


    所以,《了不起的Chrome浏览器》我还是会写下去的!


    欢迎关注寒雁Talk公众号,关注《了不起的Chrome浏览器》系列博客,与我一起见证大前端的星辰大海!


    参考资料


    • Chrome 93: Multi-Screen Window Placement, PWAs as URL Handlers, and More

    • V8 release v9.3

    • Object.hasOwn

    • ALPACA Attack

    • ALPACA: Application Layer Protocol Confusion - Analyzing and Mitigating Cracks in TLS Authentication

    • ALPACA – the wacky TLS security vulnerability with a funky name

    • Hackers can mess with HTTPS connections by sending data to your email server

    • My thoughts on the ALPACA Attack (Detailed analysis)

    • The ALPACA Attack explained

    • Cookie 的 SameSite 属性

    • SSL/TLS协议运行机制的概述

    • Sweet32: Birthday attacks on 64-bit block ciphers in TLS and OpenVPN

    • On the Practical (In-)Security of 64-bit Block Ciphers Collision Attacks on HTTP over TLS and OpenVPN

    • 剪贴板操作 Clipboard API 教程

    • Verify phone numbers on the web with the WebOTP API

    • Verify a phone number on desktop using WebOTP API


    招聘


    阿里巴巴业务平台事业部长期招聘P6及以上前端大佬,参与建设最前沿的阿里前端生态系统,推动行业技术发展,内推地址:hanyan.lk@alibaba-inc.com


    欢迎大家关注我的微信公众号寒雁Talk




    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存