零、前言
前段时间做了个跟Freebuf(http://www.freebuf.com/)相关的小应用,需要模拟登陆,也研究了很长时间,感觉也比较有意思,就把这个分享一下。因为之前在t00ls发过了,不想再截图了,就直接用里面的图片,不过会有水印。
一、登陆逻辑分析
一般来说,用程序模拟登陆,抓个包,看一下发送的数据和地址,直接POST发送即可。但Freebuf毕竟是个安全类的网站,它的登陆是不在本站的,如果点击登陆进入的是这样一个地址
首先它跳转到了另外一个域名,而且使用的是https协议,另外注意一下它后面带的几个参数,一般的登陆地址是没有这些参数的。那么我们正常的登陆测试一次。首先打开登陆地址
用户名密码验证成功后跳转到这么一个点击头像授权界面
点击头像验证后跳转到首页,至此登陆结束!那么我们可以将登陆分为以下几步
1、点击登陆,打开登陆界面
2、输入用户名、密码、验证码
3、第二步验证成功后进入授权页面
4、点击头像授权并自动跳转到首页
我们进一步分分析
0x01抓取登陆地址
首先我们看第一步,一般来说这一步我们是不用管的,我们只需手动记下登陆地址即可,但是这里需要注意一个参数state,比如前面那个登陆地址就有一个
state参数,这个参数在登陆过程中是唯一的,而且每次重新打开登陆地址就会发生变化。也就是说这个登陆地址是动态变化,即使我们记录下来也只能用一次,所以首先要能够动态的获取登陆地址。我们抓一下点击登陆的数据包
可以看到是一个302跳转,跳转的地址为:
https://account.tophant.com/login.html?response_type=code&client_id=b611bfe4ef417dbc&state=c1734ed326f4ba1e0edf4a7253635a7d&redirectURL=http://www.freebuf.com
这才是真正的登录地址,可以看到state是一个32位的随机字符串。在一次登陆的过程中这是唯一的。
0x02抓取Cookie
登陆的最终目的主要抓取Cookie,抓到了关键Cookie就象征着权限,当我们打开登陆地址时可以看到浏览器已经捕获到一个Cookie了,名为PHPSESSID,那么这个Cookie是什么时候发送过来的呢?我们看一下打开登录地址的数据包
可以看到头信息中有一个Set-Cookie的字段,这个应该就是设置Cookie的可,看起来只需要在打开这个链接的时候抓取这个字段保存即可。那么先尝试第一步登陆(这里先只说程序的思想),程序里设置三个变量,分别保存用户名、密码和验证码,验证码以图片的形式下载先来然后手动输入(还没有能力做验证码识别啊~~,不过有别人写好的模块也许可以试试)。到这一步看似没有问题,但实际在测试的时候总是出现验证码错误,难道是输入错误么,但不可能每次都输入错误。在这一步卡了下,后来发现这一步登陆的Cookie实际是和验证码绑定的,如果直接打开验证码实际是这样的
刷新一下,验证码变化一次Cookie不变,如果将Cookie删除可以看到会返回一个新的Cookie。那么就可以解释为什么出现验证码错误了,当我们去下载验证码图片的时候相当于更新了在这里记下的Cookie。这样,我们的验证码就和Cookie不对应了,所以我们要在下载验证码图片的时候同步获取Cookie。这样我们构造用户名、密码、验证码的数据包携带Cookie再进行发送,即可完成这一步登陆
可以看到提示“success”,并且返回了另一个关键Cookie—-Key_auth,这个Cookie要在下一步用到。
0x03点击头像验证
点击头像认证时向服务器发送了之前获取两个关键Cookie:PHPSESSID和Key_auth。同时向服务器发送了一个Token参数
Token参数在html中被设置成了hinden属性,被隐藏了起来,所以在之前登陆的界面下是看不到的,只有在源代码下才能看到
当我发送这个数据包时,返回的结果却是验证码错误,这里就很奇怪,因为并没有输入验证码的操作
[]{"ac":"error","msg":"\u9a8c\u8bc1\u7801\u9519\u8bef\uff01","url":"\/login.html","delay":3,"token":null}其中的"\u9a8c\u8bc1\u7801\u9519\u8bef\uff01"就是验证码错误,即使抓取正常登陆的数据包,结果也是这样,在这里蛋疼了很长时间,最后总结出这个返回数据没有任何作用。那么点击头像我们想要得到什么样的结果呢?抓包发现,一个成功的点击头像授权返回的数据包是这样的
这是一个302跳转的数据包,我们要的是中间那个Location那个字段所要跳转到的地址,注意,如果登陆地址你是复制粘贴的而不是像第一步那样获取的,那么你的state参数一旦使用一次之后再登陆就会出现这样的错误
可以看到如果成功的话location的值大约是这个样子
http://www.freebuf.com/oauth?code=010774130ec0356af5897b69524d7448728f36de&states=3c84127127bfb2d93c13785f77bf8ca3&redirectURL=http://www.freebuf.com
和我们的登陆地址的参数是一致的(注意一下,登陆地址全程都没有变化,变化的只是POST或GET的操作)
https://account.tophant.com/login.html?response_type=code&client_id=b611bfe4ef417dbc&state=c1734ed326f4ba1e0edf4a7253635a7d&redirectURL=http://www.freebuf.com
其中code=010774130ec0356af5897b69524d7448728f36de得到一个值(第三方验证的终极目的就是拿到这个code),就是表示我们在第三方平台(account.tophant.com)的验证的成功了,头信息中的location是会自动跳转的,所以下一步又会返回到www.freebuf.com
0x04获得Freebuf的权限
注意我们之前获取的Cookie(PHPSESSID和Key_auth)都是account.tophant.com域名下的,在Freebuf里是没有用的。那么看一下location跳转后返回的数据
可以看到这里就有了Freebuf下的Cookie,其中抓到两个以WordPress开头的关键Cookie即可,由于这里都是302自动跳转的数据包,浏览器会自动跳转,某些代码也会自动跳转,例如java中的HttpClient
//得到HttpClient对象 HttpClient getClient = new DefaultHttpClient(); //禁止自动跳转 HttpParams params = getClient.getParams(); params.setParameter(ClientPNames.HANDLE_REDIRECTS, false);
要设置禁止自动跳转,否则就无法获取302跳转这样的中间态,也就无法抓到cookie了。至此我们就理清了整个登陆逻辑,这里我做了一个流程图,简单说明整个过程。
0x05代码实现
这里我用java实现了整个过程,程序大约有几百行,就不直接贴代码了,用网盘分享了
链接: http://pan.baidu.com/s/1dEdMgxz 密码: 76ae