驱蚊器喵的翻译平台

Can you hear the gravity?

  1. 1. 尝试一下

本文讲述了如何使用 Cloudflare Worker 来调用 API ,识别用户注册时使用的密码是否已经泄漏。而 Cloudflare Worker 是一项 Serverless 服务,无需提供服务器,可以很方便的部署代码。


原文地址:https://blog.cloudflare.com/using-cloudflare-workers-to-identify-pwned-passwords/
原文标题:Using Cloudflare Workers to identify pwned passwords
原文作者:John Graham-Cumming
原文写于:2018/2/26 GMT+8 下午8:04:56

译者:驱蚊器喵#ΦωΦ
翻译水平有限,有不通顺的语句,请见谅。


上周,Troy Hunt 发布出了自己的 Pwned Password(已被泄漏的密码) v2 服务,该服务的 API 由 Cloudflare 使用巧妙的匿名方案处理和缓存 。

以下的perl代码可以检查密码是否存在于 Troy 的数据库中,但无需将密码发送给 Troy。相关工作原理的详细信息,请参见上面的博客文章。

1
2
3
4
5
6
7
8
9
use strict;
use warnings;

use LWP::Simple qw/$ua get/;
$ua->agent('Cloudflare Test/0.1');
use Digest::SHA1 qw/sha1_hex/;

uc(sha1_hex($ARGV[0]))=~/^(.{5})(.+)/;
print get("https://api.pwnedpasswords.com/range/$1")=~/$2/?'Pwned':'Ok', "\n";

用其他语言(例如 JavaScript )实现相同的检查同样容易,这让我意识到,我可以将检查合并到 Cloudflare Worker 中。在 JavaScript 朋友的帮助下,我编写了以下 Worker

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
addEventListener('fetch', event => {
event.respondWith(fetchAndCheckPassword(event.request))
})

async function fetchAndCheckPassword(req) {
if (req.method == "POST") {
try {
const post = await req.formData()
const pwd = post.get('password')
const enc = new TextEncoder("utf-8").encode(pwd)

let hash = await crypto.subtle.digest("SHA-1", enc)
let hashStr = hex(hash).toUpperCase()

const prefix = hashStr.substring(0, 5)
const suffix = hashStr.substring(5)

const pwndpwds = await fetch('https://api.pwnedpasswords.com/range/' + prefix)
const t = await pwndpwds.text()
const pwnd = t.includes(suffix)

let newHdrs = new Headers(req.headers)
newHdrs.set('Cf-Password-Pwnd', pwnd?'YES':'NO')

const init = {
method: 'POST',
headers: newHdrs,
body: post
}

return await fetch(req.url, init)
} catch (err) {
return new Response('Internal Error')
}
}

return await fetch(req)
}

function hex(a) {
var h = ""
var b = new Uint8Array(a)
for(var i = 0; i < b.length; i++){
var hi = b[i].toString(16)
h += hi.length === 1?"0"+hi:hi
}
return h
}

这个 Worker 可以用于拦截通过 Cloudflare 网络到 Cloudflare 站点的请求。Worker 会查看 POST 请求,并从中提取出一个名为password的字段,然后根据 Troy Hunt 的服务对其进行检查。

接着,Worker 会添加一个 HTTP 请求头,Cf-Password-Pwned,其值YESNO,取决于是否能在数据库中找到这条密码。

POST 请求将被传递到源站服务器进行处理,并插入额外的标头。例如,可以在注册页面上使用它来检查,用户注册时希望使用的密码是否已存在泄漏的数据库中。而服务器仅需查看返回结果中的标头。

显然,这块代码还没有完全准备好在生产环境上运行(例如,没有对失败的请求进行处理的部分),但它很好地说明了 Cloudflare Worker 的功能,作为 Cloudflare 正常请求处理的一部分,执行对 API 的子请求,并在请求时增加信息的能力。

尝试一下

为了进行测试,我创建了一个简单的页面,该页面将接收到的 HTTP 请求标头返回为文本,我将其部署为’signup(注册)’页面,并将上面的 Worker 代码路由绑定到该页面。

Screen-Shot-2018-02-26-at-11.23.45

我们来检查一个简单的没有由 Worker 处理的 GET 请求(注意,Cf-Password-Pwned 头不存在)

1
2
3
4
5
6
7
8
9
10
$ curl https://signup.example.com
Host: signup.example.com
Connection: Keep-Alive
Accept-Encoding: gzip
Cf-Ipcountry: US
Cf-Ray: 3f329308132f92b8-SJC
X-Forwarded-Proto: https
Cf-Visitor: {"scheme":"https"}
Accept: */*
User-Agent: curl/7.26.0

但是带有密码的 POST 请求结果附带额外的标头。从结果可以明显看出,人们不应该使用12345这样的密码。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ curl -X POST -d 'password=12345' https://signup.example.com
Host: signup.example.com
Connection: Keep-Alive
Accept-Encoding: gzip
Cf-Ipcountry: US
Cf-Ray: 3f3294e714a36d42-SJC
Content-Length: 130
X-Forwarded-Proto: https
Cf-Visitor: {"scheme":"https"}
Content-Type: application/x-www-form-urlencoded
Accept: */*
Cf-Password-Pwnd: YES
User-Agent: curl/7.26.0

但目前看来密码kRc4qMwAtexDVZVygPnSt7LP5jPFsUDt是安全的(译者注:根据标头来看,这个密码没有出现在已泄漏的密码数据库中,但是一旦本文发布后,这个密码就已经出现在网络上,所以也不安全了😂):

1
2
3
4
5
6
7
8
9
10
11
12
13
$ curl -X POST -d 'password=kRc4qMwAtexDVZVygPnSt7LP5jPFsUDt' https://signup.example.com
Host: signup.example.com
Connection: Keep-Alive
Accept-Encoding: gzip
Cf-Ipcountry: US
Cf-Ray: 3f329675e7f29625-SJC
Content-Length: 157
X-Forwarded-Proto: https
Cf-Visitor: {"scheme":"https"}
Content-Type: application/x-www-form-urlencoded
Accept: */*
Cf-Password-Pwnd: NO
User-Agent: curl/7.26.0

Cloudflare Workers 的强大功能,来自能够在 Cloudflare 的全球边缘节点上运行针对 Service Workers API 编写标准 JavaScript 的能力。一小片段的代码片段可用于转换、优化请求和响应、调用多个 API 来构建响应、以及与 Cloudflare 的缓存交互。

你可以在开发人员文档中了解更多内容。

本文作者 : meow
This blog is under a CC BY-NC-SA 4.0 Unported License
本文链接 : https://translation.meow.page/post/using-cloudflare-workers-to-identify-pwned-passwords/

本文最后更新于 天前,文中所描述的信息可能已发生改变