freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

利用HTTP参数污染方式绕过谷歌reCAPTCHA验证机制
2018-06-03 13:00:38

利用HTTP参数污染方式绕过谷歌reCAPTCHA验证机制

今年初,我上报了一个谷歌reCAPTCHA验证码绕过漏洞,该漏洞在于能用一种HTTP参数污染的不安全方式,让Web页面上的reCAPTCHA构造一个针对 /recaptcha/api/siteverify 的请求,在这种情况下,攻击者可以每次都能绕过reCAPTCHA的安全验证机制。之后,谷歌从reCAPTCHA API的顶层接口上对这个漏洞进行了修复。在此,我们一起来看看reCAPTCHA机制是如何被绕过的。

reCAPTCHA验证机制介绍

reCAPTCHA是谷歌提供的一项免费验证服务,可以方便Web应用开发者把验证码认证(CAPTCHA)机制添加到一些需要进行人机身份验证或其它形式验证的网站中。reCAPTCHA服务存在很多实际用例,比如,有时候它会用你登录网站的cookie进行验证,而有时候它又会让用户手动地去完成一些它提供的识别测试。

我是从对某目标网站的访问中发现这个漏洞的。当访问目标网站之后,就像下图一样,网站需要验证用户身份,此时,调用了谷歌 reCAPTCHA API 接口显示一组图片或数字,让用户进行选择:

利用HTTP参数污染方式绕过谷歌reCAPTCHA验证机制

当用户点击验证码CAPTCHA进行“验证”(Verify)时,会触发一个指向访问网站的HTTP请求,该请求大致如下:

POST /verify-recaptcha-response HTTP/1.1
Host: vulnerable-app.com
recaptcha-response={reCAPTCHA-generated-hash}

之后,目标访问网站需要调用谷歌的reCAPTCHA API接口,让用户对该API提供的验证作出测试,然后根据该测试响应来验证用户身份。调用谷歌reCAPTCHA API接口过程的POST请求如下:

POST /recaptcha/api/siteverify HTTP/1.1
Content-Length: 458
Host: www.google.com
Content-Type: application/x-www-form-urlencoded
recaptcha-response={reCAPTCHA-generated-hash}&secret={application-secret}

其中, {application-secret} 是用来对目标网站的验证,而 {reCAPTCHA-generated-hash} 是向谷歌reCAPTCHA API接口发送的一个响应查询,如果用户的最终测试是正确的,则API会返回以下响应信息:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 90
{
  "success": true,
  "challenge_ts": "2018-01-29T17:58:36Z",
  "hostname": "..."
}

这个响应信息最终会被目标访问网站接收到,之后,根据这个响应信息进行处理,最终会允许用户去访问到相应的网站资源。

HTTP 参数污染  

HTTP 参数污染,或者叫HPP,是网站在接受用户输入时,将其用于生成发往其它系统的 HTTP 请求,并且不校验用户输出的时候发生,这主要是源于不同的网站对不同请求参数的处理方式不同。

HTTP 参数污染可能存在客户端或服务端等很多地方,其风险程度也依不同环境而有所不同,在一些特定场景或实际应用中,它可以导致数据泄露,但在另外一些用例中,它也可能仅只是一个低风险漏洞。

我们这里的谷歌reCAPTCHA绕过过程中,需要用到目标访问网站中的HTTP参数污染方法,因此,这个绕过方式的特殊需求构造,最终也降低了谷歌对该漏洞的分类评级。

以下为存在reCAPTCHA绕过可能的目标网站请求实例:

private String sendPost(String CaptchaResponse, String Secret) throws Exception {
    String url = "https://www.google.com/recaptcha/api/siteverify"+"?response="+CaptchaResponse+"&secret="+Secret;
    URL obj = new URL(url);
    HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

其中的字符串连接符 + 是用来连接不同的url变量。

需要注意的是,在谷歌的API服务器后端,发送以下两个HTTP请求,会得到相同的响应消息。

POST /recaptcha/api/siteverify HTTP/1.1
Host: www.google.com
...
recaptcha-response={reCAPTCHA-generated-hash}&secret={application-secret}
POST /recaptcha/api/siteverify HTTP/1.1
Host: www.google.com
...
recaptcha-response={reCAPTCHA-generated-hash}&secret={application-secret}&secret={another-secret-application-secret}

两个POST请求中都有 response 和 secret 参数。在第二个POST请求中,谷歌的reCAPTCHA API 总会采用其中的第一个secret参数,从而忽略掉第二个secret参数。严格来说,这不是一个reCAPTCHA API 本身存在的漏洞,而是一种误用机制,但可以被用来进行深入的攻击利用。

漏洞利用关键点

Web开发人员需要以自动化的方式测试他们的应用程序,为此Google提供了一种在临时模拟环境中“禁用”reCAPTCHA验证的简单方法。可以点击这里的Google说明文档来参阅,总之,如果要禁用reCAPTCHA验证,请使用下面所示的硬编码站点和密钥:

Site key: 6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI

Secret key: 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe

测试利用PoC

现在,我们有了所有必须的测试要素,我们来看看如何利用:

POST /verify-recaptcha-response HTTP/1.1
Host: vulnerable-app.com
recaptcha-response=anything%26secret%3d6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe

如果目标访问网站可能存在HTTP参数污染,而且其URL链接是在secret参数之前通过添加response参数来构建的,那么这种情况下的 reCAPTCHA 验证方式有可能被绕过。

请注意,我要向目标访问网站发送一个经过构造的假冒响应消息,其中包括以下几个属性:

anything: 仅代表一个占位符

%26: 一个经url编码的&符号字符

secret: 我要进行“注入”的参数名称

%3d: 一个经url编码的=符号字符

6Le…JWe: 禁用 reCAPTCHA 验证响应的secret key,也是我们要用到的第一个secret参数

组合起来之后,就形成了以下由目标网站向谷歌 reCAPTCHA API 发送的一个HTTP请求:

POST /recaptcha/api/siteverify HTTP/1.1
Host: www.google.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Python-urllib/2.7
recaptcha-response=anything&secret=6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe&secret=6LeYIbsSAAAAAJezaIq3Ft_hSTo0YtyeFG-JgRtu

这个请求中包含了两个secret参数,由于目标访问网站存在HTTP参数污染可能,所以其中第一个secret参数可由攻击者控制,这个参数 6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe 也是谷歌官方给出的禁用 reCAPTCHA 验证方法的secret key;第二个secret参数由目标访问网站自己控制。假定谷歌的  reCAPTCHA API 采用了第一个secret参数,那么也就间接禁用了 reCAPTCHA验证,则该请求的响应总会是以下这个:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 90
{
  "success": true,
  "challenge_ts": "2018-01-29T17:58:36Z",
  "hostname": "..."
}

这样一来,在目标访问网站处理过这个请求响应之后, reCAPTCHA 会被禁用而绕过,而攻击者也自然会获得对网站资源的访问权限。

谷歌从顶层API上的修复措施

谷歌决定在他们的REST API中来修复这个问题,我认为这是一个非常明智操作。谷歌的修复其实也很简单:如果对 /recaptcha/API/siteverify 的HTTP请求包含两个同名的参数,则会返回一个错误消息。通过这种修复方式,可以保护易受HTTP参数污染攻击和reCAPTCHA绕过影响的Web应用,而且无需任何更新补丁,非常棒!

在野利用

要在Web应用程序中利用此漏洞,有两个必须的要求:首先,Web应用程序在创建reCAPTCHA url时存在HTTP参数污染漏洞:在Github中,我用搜索方法发现,集成有reCAPTCHA验证方式的Web开发架构中有约60%都会受到HTTP参数污染攻击。

其次,易受HTTP参数污染攻击的Web应用需要首先创建具有response参数的url,然后再创建secret参数,也就是形如这样的url参数:“response=…&secret=…”,但很奇怪的是,几乎所有采用reCAPTCHA验证的的Web应用都是使用了 “secret=…&response=…”这种参数格式,我想可能是谷歌的文档和代码示例就是这样规范的,其它框架估计只是复制了这种格式。谷歌在这里就很走运了…如果他们反过来这样做,这个漏洞会影响到更多网站。GitHub搜索显示,只有5%到10%的reCAPTCHA验证机制存在这个response参数在前且secret参数在后的构造要求。

所以,如果我想在野外利用这个漏洞,那么最后只有大约3%的使用reCAPTCHA验证的站点存在这种漏洞,与其它漏洞相比,虽说影响范围和威力较小,但多少还能构成一些安全威胁。总结来说,作为开发者,请慎用字符串连接来构建请求字符串url,尽可能使用字典方式来储存密钥和键值,然后再进行url编码;作为安全测试方来说,HTTP参数污染是个不错的渗透测试方式。

漏洞上报进程

2018-Jan-29 / 上报谷歌

2018-Jan-30 / 谷歌回复: “reCAPTCHA 机制没啥毛病啊!?“

2018-Jan-31 / 我请求谷歌方面认真阅读我的漏洞报告

2018-Jan-31 / 谷歌要求我提供更多测试证明

2018-Feb-1 /  谷歌确认漏洞

2018-Feb-15 / 谷歌奖励我$500美金,我转手把这点钱捐赠给了慈善机构

2018-Mar-25 / 谷歌修复漏洞

*参考来源:andresriancho,FreeBuf 小编 clouds 编译,转载请注明来自 FreeBuf.COM

# reCAPTCHA # HTTP # 参数污染
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者