天天看点

Chrome 93 支持 Error Cause,阿里巴巴前端推进的国内首个 ECMAScript 提案可以用了!TL;TR详细解读

作者|寒雁Talk Alibaba F2E  8月31日

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

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

详细解读

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万。

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

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

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重写,这就有点尴尬了...

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

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

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

Chrome 93 支持 Error Cause,阿里巴巴前端推进的国内首个 ECMAScript 提案可以用了!TL;TR详细解读

图片来源: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端口能用了?

为了预防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 cookie
url += "?";
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了。

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

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

Chrome 93 支持 Error Cause,阿里巴巴前端推进的国内首个 ECMAScript 提案可以用了!TL;TR详细解读

视频来源: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,不再需要手动复制粘贴验证码,其流程如下图:

Chrome 93 支持 Error Cause,阿里巴巴前端推进的国内首个 ECMAScript 提案可以用了!TL;TR详细解读

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

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

说明
WebOTP API支持跨设备
支持在跨域的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、文件等多种格式,功能越来越强大:

2021-09-21 Chrome 94 Clipboard API支持从剪贴板读取保留metadata的原始PNG文件
Clipboard API支持复制粘贴SVG
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

参考资料

  • V8 release v9.3
  • ECMAScript 双月报告:阿里巴巴提案 Error Cause 进入 Stage3
  • 我国首个 JS 语言提案在 ECMA 进入 Stage 3
  • 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

继续阅读