Security is Hard, Y’all
Security is Hard, Y’all
安全真的很难
It started innocently enough. I saw a tweet about a new product offering from one of my favorite companies, Cloudflare. Neat! I clicked through to the site and there it is: And huzzah!, my preferred handle, @ericlaw is still available. I’d better hurry to claim it before someone else gets it! 事情的起因很单纯。我看到一条推文,介绍了我最喜欢的公司之一 Cloudflare 推出的新产品。太棒了!我点击链接进入网站,发现我心仪的账号名 @ericlaw 居然还没被注册。我得赶紧抢注,免得被别人捷足先登!
Since I’m already a long-time Cloudflare user, I just need to sign in. That makes sense, how else will they bind the handle to my account? Easy peasy. I’m in. Looks like there’s just one more step, I gotta authorize the new feature? But wait a sec! This looks exactly like one of those Consent Phishing attacks that have been so popular over the last few years! 作为 Cloudflare 的长期用户,我只需要登录即可。这很合理,否则他们怎么把账号名绑定到我的账户上呢?轻而易举,我登录进去了。看起来只剩最后一步了,我需要授权这个新功能?但等一下!这看起来简直就像过去几年里非常流行的“同意钓鱼”(Consent Phishing)攻击!
And wait, why is the entry point on cloudflare.pay, a site that doesn’t already have my credentials, rather than something within the cloudflare.com domain which does (e.g. cloudflare.com/pay)? There is no inherent technical relationship between a .com domain and a .pay domain. Domain names under the .pay sTLD are available to anyone with $20 (unlike, e.g. .bank which requires more vetting), so there’s nothing that would stop me from registering my own cloudflarepayments.pay domain name in just a few minutes. 等等,为什么入口是在 cloudflare.pay 这个网站上,而不是在已经拥有我凭证的 cloudflare.com 域名下(例如 cloudflare.com/pay)?.com 域名和 .pay 域名之间在技术上没有任何内在联系。.pay 顶级域名(sTLD)只要花 20 美元谁都能注册(不像 .bank 那样需要严格审核),所以完全没有任何东西能阻止我在几分钟内注册一个属于我自己的 cloudflarepayments.pay 域名。
And why doesn’t Cloudflare’s permission site recognize its own company’s feature? And that green checkmark looks suspicious as heck– an attacker could probably just shove that emoji inside their misleading display name, the same way that folks trying to phish Microsoft email accounts use misleading app names and icons. 而且,为什么 Cloudflare 的授权页面识别不出自家公司的功能?那个绿色的勾选标记看起来极其可疑——攻击者完全可以把那个表情符号塞进他们误导性的显示名称里,就像那些试图钓鱼微软电子邮件账户的人使用误导性的应用名称和图标一样。
The guys at Cloudflare are geniuses who know their stuff. This has got to be an attack. It’s a clever one — I was feeling such a sense of urgency because I wanted to “win” the race to get my desired handle. Very very clever! Unfortunately, the Cloudflare permission page doesn’t follow best practices, so there’s no “Report suspicious request” link I can use to let the Cloudflare folks know that their customers are under attack. Cloudflare 的团队都是天才,他们非常专业。这一定是一次攻击。而且是一次聪明的攻击——我当时感到非常紧迫,因为我想在抢注中“获胜”,拿到我想要的账号名。真是太聪明了!遗憾的是,Cloudflare 的授权页面没有遵循最佳实践,所以没有“举报可疑请求”的链接,让我无法告知 Cloudflare 团队他们的客户正受到攻击。
Let me go back to my Cloudflare dashboard and try to get to the Wallet feature from its sidebar. Hrm. It’s not there. Now, Wallet purports to be “a new feature”, so maybe the Dashboard just isn’t updated yet. A search of the docs turns up nothing. Let’s ask the AI agent in chat. The very first thing the chat agent wants is access to my account. 让我回到 Cloudflare 控制面板,尝试从侧边栏进入 Wallet 功能。嗯,没有找到。Wallet 声称是“一项新功能”,所以也许是控制面板还没更新。搜索文档也一无所获。让我们问问聊天机器人 AI。聊天机器人做的第一件事就是要求访问我的账户。
This feels a little weird, but the page is still cloudflare.com so I guess I can give the thing access to things it already has access to. Weirdly, the AI agent first proposes that I grant it full control rather than read-only access, which feels like a failure of the principle of least privilege, but I don’t actually need to ask an account specific question anyway. After granting read permission, the agent allows me to ask my question: Oh, wow. Cloudflare says it really is an attack! Let’s report the phish right away! 这感觉有点奇怪,但页面确实还在 cloudflare.com 下,所以我想我可以给它一些它本来就已经有权限访问的东西。奇怪的是,AI 代理首先建议我授予它完全控制权,而不是只读权限,这感觉违背了“最小权限原则”,但反正我也不需要问什么涉及账户的具体问题。在授予只读权限后,代理允许我提问:噢,天哪。Cloudflare 说这确实是一次攻击!赶紧举报这个钓鱼网站!
A few minutes later… womp womp… Oh dear. After a few minutes of further frantic searching, it turns out that this is, in fact, a legitimate new Cloudflare product and a legitimate site, despite giving every indication of being a clever phishing attack. It further turns out that that suspicious green checkmark is not part of the app’s untrustworthy display name but instead a (poorly placed) security UI element that a user is expected to hover over to get the security details. 几分钟后……哎呀……天哪。在又经过几分钟疯狂的搜索后,结果发现这实际上是 Cloudflare 一个合法的新产品和一个合法的网站,尽管它表现得就像一次聪明的钓鱼攻击。进一步发现,那个可疑的绿色勾选标记并不是应用不可信显示名称的一部分,而是一个(放置位置很糟糕的)安全 UI 元素,用户需要将鼠标悬停在上面才能查看安全详情。
The Cloudflare folks apparently want security issues reported via HackerOne (which wouldn’t let me log in because the Cloudflare CAPTCHA HackerOne uses seems to be broken…). When legitimate websites sometimes act very very phishy, consider how hard it must be for URL Reputation services like Microsoft SmartScreen and Google SafeBrowsing to block malicious sites without false positives as millions of new sites are added to the web every week. Cloudflare 团队显然希望通过 HackerOne 报告安全问题(但我无法登录,因为 HackerOne 使用的 Cloudflare 验证码似乎坏了……)。当合法的网站有时表现得如此像钓鱼网站时,你可以想象,对于像 Microsoft SmartScreen 和 Google SafeBrowsing 这样的 URL 信誉服务来说,在每周有数百万个新网站加入互联网的情况下,想要在不产生误报的情况下拦截恶意网站是多么困难。
Lessons
教训
Web Developers, please follow every best practice, I’m begging you: Web 开发人员,请遵循每一项最佳实践,我求求你们了:
- Host apps and content under your trusted domain name (e.g. cloudflare.com/pay or pay.cloudflare.com). 将应用和内容托管在你们受信任的域名下(例如 cloudflare.com/pay 或 pay.cloudflare.com)。
- If you must add a new name, link to it directly from a page on your trusted domain name. 如果必须添加新域名,请直接从受信任域名下的页面链接过去。
- Show relevant security information in a trustworthy place when asking the user to make security decisions. 在要求用户做出安全决策时,在可信的地方展示相关的安全信息。
- Make it trivial to report scams, in context (e.g. on the permission request page). 让举报诈骗变得简单,并提供上下文(例如在权限请求页面上)。
- Test your security reporting flows to ensure they are monitored and function correctly. 测试你们的安全举报流程,确保它们受到监控且运行正常。
Users: Try to stay safe out there. Think before you click, and if all else fails, wait. 用户: 在网上要保持安全。点击前先思考,如果实在拿不准,就等等。
Security Geeks: Never blame the victim– they’ve got an impossible job. 安全极客: 永远不要责怪受害者——他们面对的是一项不可能完成的任务。