把秘密账号当作凭据:审计它
如果知道号码就能让人登录或拉取配置,它就是凭据。执行权限、存储、猜测率和轮换检查。
标着“账号”的字段并不会自动成为公开标识,标签也不是检验。检验的标准是持有它能做什么:如果知道号码就能让人登录、下载连接配置或授权设备,那么这个号码就是有生命周期的凭据。每当服务发放一个数字身份并称其无害时,我都会做下面五项检查。每项检查在简短记录中留下一行,而记录本身就是交付物,不是对产品的判决。
清点持有究竟授予了哪些权限
把号码解锁的每个动作分别写下来。登录门户、获取配置文件、授权新设备和提供被接受的隧道登录是不同的权限,一项服务可以只实现其中一个而不实现其余。只把号码当作唯一字段接受的门户,并不能说明 隧道如何认证对端 以及之后流量密钥如何派生。
通用模型很容易表述:bearer 凭据是指持有者无需证明持有单独密钥即可使用的凭据,这正是 RFC 6750 为令牌划出的区别。这是类比,不是声称基于号码的服务实现了 OAuth。如果持有者不需要别的,就把号码当作 bearer 秘密,并据此分类设计的其余部分。
把它当秘密保护,而不是当公开标识
存储方式由分类决定。能让人登录的值应放在密码管理器中,而不是截图、剪贴板历史、聊天消息或浏览器便签里。截图是常见的泄露途径:号码很短,看上去无害,于是留在了一个比它来源设备活得更久的支持帖里。
钓鱼是另一种失效方式,它不在乎号码有多随机。想要这个值的骗子会请你把它粘贴到表单里,而一个永不过期、没有第二因素的凭据值得一试。请从书签或已知地址进入登录路径,不要从同时索要号码的消息链接进入。
把恢复材料当作秘密的一部分。如果运营方还发放了恢复码、PIN 或可重置账号的邮箱地址,那些是适用同样保护要求的独立凭据。一条不受保护的找回通道会让其他所有控制变成装饰。
把抗猜测与速率限制放在一起检查
长度只有和生成方式放在一起才有意义。由可预测序列生成的长号码,比密码学生成器产生的短值更弱,位数惊人并不能证明不可预测。在推断它有多难猜之前,先问这个值是怎么生成的。
单靠抗猜测也扛不住不限次数的尝试速率。真正重要的是运营方实现的那些控制:失败计数、锁定、按来源限流,以及错误号码能否与不存在的号码区分开。如果服务支持,一次失败尝试就能看出错误长什么样,以及是否出现重试计数:
# one attempt, then read the response and any counter or delay
# do not script repeated guesses against a live account
curl -i -X POST https://portal.example.invalid/login -d "account=000000000000"
记录响应暴露了什么。对未知账号给出不同错误,即使号码无法猜中,也是枚举预言机;这个发现属于记录,不论你能否在客户端修复它。
在需要之前规划轮换与吊销
找到丢失或泄露号码时受支持的流程,并在一切正常时写下来。账号凭据到底能不能更换?更换会不会使已登记的设、活动会话或已下载的配置失效?流程要求哪些恢复材料?不依赖邮箱的服务可能把更多恢复责任交给用户,这使流程更重要,而不是更不重要。
把账号更换与凭据吊销分开。如果号码授权下载密钥、证书或配置文件,更换号码可能让已下载的材料仍然有效,而吊销已下载材料可能是由另一位负责人执行的另一项操作。不要假设改动一个字段就能终止所有连接;核对运营方的实际模型,并记下你在哪里验证过。
记录决定,并在此后重新核对
为每项服务保留一页记录:号码授予哪些权限、存放在哪里、谁能重置、有哪些使用证据,以及泄露后第一个小时你会做什么。正是这份记录把关于术语的争论变成别人可以审计的决定。
隐私主张需要自己的范围。随机生成的号码仍可能是跨时间关联账号事件的稳定标识;不可预测不等于不可关联,而这两种属性都没有说明保留的网络元数据。请比较完整的设计,而不是数登录界面上的字段。
在记录之前:
- 号码授予的每一项权限都已列出,包括下载和设备授权。
- 存储与恢复通道按与号码本身相同的标准保护。
- 生成方式和速率限制是已知的,而不是由长度推定的。
- 存在更换流程和吊销流程,并且你知道哪个取消哪个。
- 记录写明了谁能重置该值,以及使用后还留下什么证据。