自2015年以来,我们一直在用一种主动、积极的方法来吸引世界各地的开发人员,帮助他们建立技能来保护他们的代码,减少返工和补救,并希望将安全团队视为有趣的警察之外的东西。
我们仍然致力于与开发人员并肩作战,确保整个银河系的代码安全,但现在是时候摇身一变,把我们身经百战、具有安全意识的开发人员带到下一个层次。
我们很高兴地宣布在Secure Code Warrior 平台上发布一个全新的功能:Missions 。这个全新的挑战类别是开发人员安全培训的下一阶段,使用户从回忆安全知识,到在真实世界的模拟环境中应用它。这种脚手架式的微观学习方法建立了强大的安全编码技能,与工作相关,并且比(垂直)在工作日的背景中观看无尽的培训视频更有娱乐性。
我们第一个可玩的公共任务是模拟GitHub Unicode漏洞。它可能看起来很简单,但这是一个非常聪明的漏洞,剖析起来很有趣。安全研究员0xsha做了一个全面的案例研究,说明这个同样的漏洞如何通过案例转换的方式来利用Django,同时还揭示了该漏洞的行为在不同的编程语言之间如何变化。关于这个安全问题,还有很多东西需要发现,而我们的任务就是一个很好的开始。
GitHub的迎面(案例映射)碰撞
在2019年11月28日的一篇博文中,安全研究小组Wisdom报告了他们在GitHub上发现的一个安全漏洞。他们概述了他们是如何利用Unicode中的案例映射碰撞来触发密码重置电子邮件传递到错误的电子邮件地址(或者如果我们像攻击者一样思考,威胁行为者选择的电子邮件地址)。
虽然安全漏洞从来都不是什么好消息,但如果安全研究人员在代码库中发现了潜在的可利用的错误,他们确实提供了一些怜悯,更不用说避免灾难的机会。他们的博客和报告往往是很好的读物,了解一个新的漏洞和它是如何工作的,是一种很酷的事情。
为了提高安全编码的能力,不仅要找到常见的漏洞(尤其是任何很酷的新漏洞--我们都知道,恶意的威胁者会寻找肥沃的土地,用这些新技术挖掘一些数据),还要有安全的实践环境,了解如何利用这些漏洞,这是非常强大的。
所以,让我们来做这件事。继续阅读,发现Unicode中的Case Mapping Collision是如何被利用的,它的实时性如何,以及你如何以安全研究员的心态,自己去尝试。
准备好现在就进行一次案例映射碰撞了吗?快来吧。
Unicode。复杂、可无止境地定制,而且不仅仅是表情符号
"Unicode "可能不在普通人的词典中,但很有可能大多数人每天都以某种形式使用它。如果你使用过网络浏览器、任何微软软件,或者发送过表情符号,那么你就已经近距离接触了Unicode。它是对世界上大多数书写系统的文本进行统一编码和处理的标准,确保每个人都能使用单一的字符集(以数字方式)表达自己。目前,有超过143,000个字符,所以无论你是使用冰岛语,还是土耳其的无点字,或者任何介于两者之间的字符,你都会被覆盖。
由于Unicode的字符集数量庞大,在许多情况下需要一种将字符转换为另一个 "等价 "字符的方法。例如,如果你将一个带有无点的Unicode字符串转换为ASCII,它应该简单地变成一个 "i",这似乎是合理的,对吗?
大量的字符编码带来了巨大的潜在灾难
Unicode中的案例映射碰撞是一个商业逻辑漏洞,其核心是可以导致未受2FA保护的账户被接管。为了说明这个漏洞,让我们看看这个漏洞在一个真实代码片段中的例子。
app.post(/api/resetPassword, function (req, res) {
var email = req.body.email;
db.get(SELECT rowid AS id, email FROM users WHERE email = ?, [email.toUpperCase()],
(err, user) => {
if (err) {
console.error(err.message);
res.status(400).send();
} else {
generateTemporaryPassword((tempPassword) => {
accountRepository.resetPassword(user.id, tempPassword, () => {
messenger.sendPasswordResetEmail(email, tempPassword);
res.status(204).send();
});
});
}
});
});
其逻辑是这样的。
- 它接受用户提供的电子邮件地址,并将其大写以保持一致性。
- 它检查电子邮件地址是否已经存在于数据库中。
- 如果是这样,那么它将设置一个新的临时密码(顺便说一下,这不是最佳做法。相反,应使用带有令牌的链接,以实现密码重置)
- 然后它向步骤1中获取的地址发送一封电子邮件,其中包含临时密码(这是很糟糕的做法,有很多原因。 呀)。
让我们看看原博文中提供的例子会发生什么,一个用户请求重置密码的电子邮件John@GıtHub.com(注意土耳其的无点i)。
- 该逻辑将John@Gıthub.com 转换为JOHN@GITHUB.COM
- 它在数据库中查找,并找到用户JOHN@GITHUB.COM。
- 它生成了一个新的密码,并将其发送到John@Gıthub.com。
请注意,这个过程最后会把高度敏感的电子邮件发送到错误的电子邮件地址。哎呀!
如何赶走这个Unicode恶魔
这一特定漏洞的有趣之处在于,有多种因素使其变得脆弱。
- 实际的Unicode铸造行为
- 确定使用电子邮件地址的逻辑,即用户提供的电子邮件地址,而不是数据库中已经存在的电子邮件地址。
从理论上讲,你可以通过两种方式来解决这个具体问题,正如《智慧》的博文中所指出的。
- 用Punycode转换将电子邮件转换成ASCII码
- 使用数据库中的电子邮件地址,而不是由用户提供的地址
当涉及到加固软件时,一个伟大的想法是不留任何机会,采用尽可能多的防御层到位。据我们所知,可能还有其他方法可以利用这种编码--只是我们还不知道。任何你能做到的减少风险和关闭可能被攻击者打开的窗口都是有价值的。
准备好自己尝试一下了吗?
大多数开发人员都知道,泄露的数据对企业不利。然而,有安全意识的工程师是应对日益增长的漏洞、违规行为和网络安全困境的有力解药。
是时候把你的安全编码和意识技能提高到新的水平了。在一个身临其境的安全模拟中体验这个GitHub漏洞,你可以看到不良代码在前端和后端背景下的影响。攻击者有优势,所以让我们平分秋色,以白帽反击的方式应用真正的技能。