再看API设计——从黑客的角度
文章目录
互联网的高速发展以及多终端设备的广泛使用使得前后端分离架构变成了必须,越来越多的网络应用暴露出API以便于前端的使用,RESTFul API的设计成为了业界主流的设计范式。在持续的业务增长以及后端技术的革新中,微服务架构(Microservice)崭露头角,解决了单体应用(Monolithic Application)的诸多问题而越来越流行。现在,在客户端与服务、服务与服务之间,有更多的数据通过常用的json等结构化的方式进行交互。这些交互过程在单体应用中对外并不可见,但在微服务架构下对于却变得透明,黑客可以通过窥探及猜测系统内部的结构,会比以前更容易攻击系统。在这篇文章中,我将以一个数据黑客的角度,展示如何利用API来大规模的获取所要的信息。
数据黑客
数据黑客没有一个准确的定义,在我看来这帮人对于数据具有敏锐的嗅觉;他们尝试得到一切能够获得的数据并进行数据分析;他们尝试在数据的云海中找出规律以便预测未来。在程序员拯救世界的今天,数据黑客则掌握了世界的未来。
在若干年前,前后端分离的架构还尚未普及,很多数据的呈现方式都是直接在页面中打印出来,为了解析数据,数据黑客们使用XPATH去解析数据,将数据装入数据库进行分析,甚至从中赚钱。如今,我们有着大量的API供使用,数据变得唾手可得。我们不用再去繁琐的解析易变的HTML,只需要访问一个URL即可获得我们需要的数据。
10天内获得自由职业网站8百万项目数据
我对自由职业充满了好奇,想试一下自由职业是怎么接到活的。在Freelancer网站上,几乎每分钟都有新的项目发布,一般一分钟之内就有好几个投标信息(bid)。每个投标信息包含了投标的内容、价格以及完成时间,然后雇主根据这些信息来筛选谁可能接这个项目。一般来讲会在交谈之后,明确所有的事宜后,再将项目分配给自由职业者。
作为自由职业者,我们可以看到其他人投标的价格以及别人的信誉度、别人做过的项目等信息,但不能看到具体的投标内容。作为雇主,价格、自由职业者的信誉度、是否通过一些测试可能都是影响雇主是否第一轮筛选进行交谈。那么,通过数据分析,能否回答以下几个问题以便帮助我们正确的投标:
- 针对投标信息,雇主对自由职业者的信誉度和价格,哪个看得更重?
- 针对澳洲的雇主,我如何能够增加我被选中的几率,是通过降低价格还是提升自己的质量?
为了回答这些问题,我需要尽快的将网站上所有可能拿到的信息都拿下来进行分析。
网站及API分析
打开一个项目页面(注:你需要翻墙),你会看到页面如图所示:
简单的看一下HTML后,发现网站将所有的信息都内嵌到HTML中的一个script中,在浏览器执行完成后会得到project变量。这个变量包含了项目的所有信息,所以理论上讲,我们拿到一个HTML然后解析Javascript,是可以得到我们需要的数据的。
但这种方式也存在一些问题,一来是解析HTML非常费事,二来是执行Javascript也比较繁琐。并且没有一个办法能够遍历所有的项目,可行性并不大。
通常来讲,我不会去解析主网站,因为其防范一般比较严。但很多网站的马奇诺防线在移动端就失效了,Freelancer也不例外。
打开移动端的网页。简单看一下可以知道它是基于AngularJS写的网站。
通过分析API的请求,可以很快的看到API的样子:
我们来分析一下这个URL,红色部分代表了这个项目的简写名字,将其改为其他的项目名称以后能够得到对应的信息。
理论上我只要得到所有项目的简写名字,再用这个地址就可以获得所有的信息了。但且慢,我注意到了投标信息的API:
红色部分用的是一串数字,如果你了解RESTFul API,则很容易知道这个bids的信息是属于9844976项目的。将之前的projects后面的名字变为数字,果然返回ID为9844976的项目的信息,和用简写名字同样的效果。这样的话我就确定了网站每个项目的ID是可以直接访问的,从0开始遍历这个ID即可得到所有网站的信息。
阻力:API访问速度限制
当爬到1000个左右的时候,网站就报告API Rate Limit限制了,大概需要一个小时左右才能再次访问。作为一个大型的网站,API访问速度限制是很平常的事情。如果照这个速度访问,则爬完所有的信息需要将近一年。能不能更快呢?
通过匿名代理可以让访问的服务器无法识别出您的真实的IP地址,所以如果有大量的匿名代理,就可以满足爬虫的需求。但这个网站使用的是HTTPS,要找到大量稳定的HTTPS代理需要较高的代价,网络上常见的匿名代理网站提供的代理通常都不稳定。
那么,有没有一个更廉价的方式能够获得更多的IP地址呢?洋葱网络为我们提供可以非常好的途径来隐藏自己的真实身份,并能够得到大量稳定的IP,并且能够在达到API Rate Limit之前就更新IP地址,非常符合我们的要求。
为了让多线程并行,我在DigitalOcean的5美元的服务器上用Docker启动了10个Tor的客户端,这样每个客户端就拥有一个独立的IP,并且每10秒钟切换一次。脚本连续运行10天后,所有的数据全部到达本地。
从黑客的角度看
好的几点:
- 该网站提供了移动端的API。
- 有API的限速。
需要改进的有:
- ID号可遍历:通过将ID变为UUID,可以解决资源被遍历的问题。但这个要视业务场景来定,如果业务上并没有需要保护数据,则简单的ID也是一种选择。
- 加载的数据包含了很多额外的信息,造成一些信息泄露:在返回的数据中包含了大量的其他信息,黑客可以利用此信息得到页面上没有显示的信息。例如网站上对投标者对雇主的id、用户名等信息是不知道的,但API返回的数据中却有这些信息。这样黑客可以通过这些信息通过其他渠道联系上雇主。
- 保护网站遭受匿名网络攻击:根据业务的不同,可以设置针对地域的IP限制。例如如果网站大部分针对澳洲客户,则澳洲客户的API使用量可以设置为1千/小时,而其他国家则设置为100个/小时,并且在适当时候显示验证码。
获得一年中6亿的机票数据
由于家庭的需要,我会在节假日往返成都和广州,而我想买到最便宜的机票。那么问题在于,我需要提前多少天才能买到足够便宜的机票呢?在我得到数据之前,我曾手工的看机票的数据,但很难发现规律,往往意识到涨价的时候,已经比最低值高出了很多。如果我能持续的抓取每天看到的30天之内的机票的数据,并用于一年后的数据分析,我是否能够找到一些规律呢?
为了完成这个任务,从2012年开始,我开始从各大机票售卖网站抓取机票信息。这里想举一个从某网站中获取机票的例子来看看我们能够从中学到一些什么。
我之前说过从主站入手往往很难攻破,所以直接打开移动的网站:
只需要看一下网络的请求就可以很方便的定位到获取机票的API以及返回值:
API分析
来我们看看API中包含了些什么:
data=%7B%22searchType%22%3A%……
这部分应该是存储的数据,很简单,我们通过decodeURI即可得到可见的信息:
后面一部分是固定的串,有API的key以及版本信息
useNative=true&ttid=201300@travel_h5_3.1.0&appKey=12574478
对于爬虫来讲,最麻烦的部分在于:
t=1426062775998&sign=3feb52aed67967a2c47aa7a2b9f2a417
这部分一直在变,并且若干秒后会失效。sign的计算和cookie中的_m_h5_tk有很大的关系,并且每次服务器要返回新的_m_h5_tk的token用于下一次请求。所以如果要生成这个url,必须要将他的计算规律搞清楚。对手前端的加密来讲,基本上如果了解js的开发,能够较快的找出来。首先搜索API中包含的字符串h5apiUpdate,很容易就定位到这里:
但这部分代码已经被压缩,无法打断点。Chrome提供了一个非常棒的代码格式化工具可以方便的将代码格式化为可读性很好的代码:
再在这里打上断点,所有的秘密都呈现在了眼前:
剩下的事情就是将这个写成脚本即可,请参考后记。
总结
从这个例子中我们学到了什么:
- 可以用时间作为token来生成动态的url
- 用sign去检查请求是否合法
- 服务端可以用时间token来拒绝重发的请求
- JS端的压缩可以较为容易的破解
后记
以上的代码我都分享在我的github账号。仅用于学习用途,请勿用于恶意攻击。
后来我发现Freelancer网站有一个隐藏的API接口文档,在这个文档中还有更多的信息可以参考。另外知乎上也有一些反爬虫的一些讨论,挺有趣,可以参考。
文章作者 贺思聪
上次更新 2016-08-24
许可协议 未经原作者许可禁止转载