前言
有幸参加西电的校内赛,从web第一题就不会,Google了一下题目源码,发现此文,看了一遍,还挺好的,故此翻译,与大家分享。
原文前言
Securify会不时发布Spot The Bug challenge,以帮助人们提高漏洞挖掘技巧。 当然,这很有趣。 在这篇博文中,你可以找到为即将到来的挑战赛的热身题的writeup! 该代码源于野外遇到的一个漏洞。(The code stems from a vulnerability that was encountered in the wild. 不太会翻orz)
该代码包含绕过HMAC检查的漏洞。请注意,这是一个热身挑战,不会给解决者提供奖金(之后的题目都会给予奖金)。
代码
此脚本为用户提供的主机执行DNS查找。它使用HMAC来确保从可信来源请求它。很好的实现,真的吗?
|
|
漏洞细节
让我们来看看代码。
- 第三到第六行,要求用户提交一个HMAC和主机名
host
。 - 一个密钥从环境变量中取得。
- 如果用户设置了
noce
,密钥被更新为secret = HMAC(SHA256, nonce, secret)
。 - 用
HMAC = HMAC(SHA256, hostname, secret)
生成一个HMAC。 - 生成的HMAC与提供的HMAC比较。
让我们花点时间记住来自加密世界的两句名言:“复杂性是安全性的最大敌人”和“永远不要推出自己的密码”。有了这个,我们可以很快看到在这个设置中出了什么问题。
如果程序员跳过步骤三,仅仅使用提供的主机名和密钥生成一个HMAC,这不会有问题。在密码学中,一个nonce
通常被用于避免消息重复或生成唯一密钥。然而,我们看这个自定义实现,密钥用nonce
的HMAC更新了。理论上这不会被直接攻击利用。但在复杂的PHP世界中,这导致了一个严重的安全漏洞。
为了正确认识漏洞,我们可以看一下,当传入一个数组作为message被提供时,hash_hmac
函数的的行为。
|
|
output:
|
|
我们可以看到,hash_hmac
仅仅触发了一个警告并返回false
。这可以通过提供一个数组作为主机名在原始代码中触发。但是,这不会绕过HMAC检查,因为使用了强比较(!==)。
|
|
因为强比较会比较数据类型,布尔值false
不能和字符串"false"
相等(但在弱比较中两者会被判定为相等)。并且,由于$_POST['hmac']
不能为布尔值false
,所以这条路行不通。
(好在,)我们的程序员决定增加额外的复杂性,无论出于何种原因,他在代码中添加了一个nonce
。
|
|
当我们为nonce
传入一个数组时会发生什么?对的,hash_hmac
会返回一个布尔值false
。然后,新的HMAC就会以HMAC = hash_hmac(SHA256, $_POST['host'], false)
的形式生成!攻击者可以为任何信息生成一个合法的HMAC。例如:
|
|
这个漏洞的exp url看起来类似:
|
|
当然,主机名参数可以执行代码,所以从这里开始游戏就结束了。
Spot The Bug 2018
我们预计今年第二季度开始时会发布Spot the Bug挑战。如果你喜欢这个挑战,你可以通过发送邮件到stb@securify.nl来订阅,我们会让你保持最新状态。