Facebook提供了一个GraphQL节点,管理员可以通过这个节点查看广告的用户点击日志。这些广告指的是那些会出现在Facebook和Instagram上的广告,可以是赞助式广告,也可以是出现在侧边栏上的常规广告,这些广告可以根据不同用户的选择和习惯来显示相应的内容。但需要注意的是,并非所有的用户都能够知道某个广告的创作者、广告开发经费、目标人群、以及账号所绑定的信用卡数据。

1.jpg

介绍

目前,Facebook还没有一份公开的GraphQL文档或指南,所以我们开始先简单介绍一下它如何使用收集到的信息来对用户进行有根据的推测。

首先,请大家按照ApolloData的这篇基础教程【传送门】来搭建一台GraphQL测试服务器,可供参考的资料还有graphql.org的这两篇文章。【资料一】【资料二

2.jpg

如果想通过Facebook查询一个对象的话,一般我们都会使用root查询来获取任意ID(用户有权限查看)的相关信息。类似页面这样的公共实体可以随意被访问,但类似广告账号这样的私人实体只有具备一定权限的用户角色才可以访问到。

3.png

Facebook给我们提供了很多种root查询,比如说,nodes可以在一次调用中接受多个ID,并返回多个对象。Root查询中的默认对象和数据域如下图所示:

4.png

侦察

通过使用Shubs(@infosec_au)和Naffy(@nnwakelam)所提供的自定义侦察技术,我们找到了能够允许我们获取更多Facebook资源的节点,那么下一步就是要弄清楚我们能够加载的数据类型。不过有了Shubs和Naffy所提供的方法,这一步操作的难度其实并不大。

Facebook使用了一种Invariant Detector(IVD),并通过这种纵深防御系统来检查授权规则中的异常查询请求,所以通过字典来测试所有可能的数据域估计就行不通了。

5.png

我们还需要尽可能地降低错误发生的次数,因为目前这个功能仍处于测试阶段,因此我们不想在Facebook的日志系统中留下太多的记录。不过幸运的是,Facebook的GraphQL还允许我们找出当前的数据类型。

6.png

既然我们已经知道了相关的数据类型,我们就可以通过查看已有资源和之前的查询请求来确定系统是否会接受这些数据域了。

7.png

PoC

为了让本文所介绍的技术真正应用到实际中,我们要做的就是想办法让用户点击一个广告,然后查看广告访问日志的响应即可。我们这里使用了一个Python脚本来导出所有使用的GraphQL调用,并给Facebook安全团队提供了一个攻击演示视频。下面是一些视频截图以及攻击者可能查看到的内容:

-广告创作者的个人Facebook账号;

-Facebook广告账号;

-账号所使用的支付方式(Mastercard/Visa/Paypal);

-信用卡卡号的最后四位数以及卡片的到期日期;

-广告的总花费;

Facebook

8.png

Instagram

9.png

总结

由于Facebook的广告账号可以被其他角色的用户查看到,因此这也就意味着其他的Facebook活动(包括广告受众和广告统计等信息)很有可能也会被他人获取到。换句话来说,当他人点击了一个广告之后,该广告不仅会将这个广告账号中所有其他的广告信息以及广告目标人群信息全部泄露出去,而且连广告制作方的信用卡信息和个人信息都泄露出去。

影响

需要注意的是,Facebook其实并不想广告的制作方被他人去匿名化,因此这个漏洞给Facebook所带来的影响不容小觑。我于2017年3月26日首次将漏洞信息上报给了Facebook的事件响应团队,经过了两个多月的沟通和努力之后,我在2017年6月6日收到了Facebook提供的一万美元漏洞奖金。

* 参考来源:philippeharewood, FB小编Alpha_h4ck编译