关于 HTTP 我不讲理论,只讲一下具体的用途。
GET 请求之发送验证码
首先我举一个例子,收过短信验证码吧,一般来说在你注册账号的时候就会用到,会有一个点击发送验证码的按钮,这里以 网址 114 预约挂号 为例
输入完手机号,点击获取验证码就能收到验证码,但这背后的原理又是啥,服务器那边怎么知道我要验证码,并且我输入正确的验证码就进入,错误的就不行。而这正是网络协议 HTTP(关于 HTTP 相关的这里不做过多讲述,希望读者能自行百度了解),我先说下点击了获取验证码发生了什么,通过抓包工具可以获取到如下请求
GET https://www.114yygh.com/web/common/verify-code/get?_time=1601308153790&mobile=15212345678&smsKey=LOGIN HTTP/1.1
Host: www.114yygh.com
Connection: keep-alive
Accept: application/json, text/plain, */*
Request-Source: PC
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4208.400
Content-Type: application/json;charset=UTF-8
Referer: https://www.114yygh.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
首先我们向服务器发送了一个如上的请求,这是一个 GET 请求,同时请求的链接(url)为https://www.114yygh.com/web/common/verify-code/get?_time=1601308153790&mobile=15212345678&smsKey=LOGIN
如果你会点英文的话,可能会理解其中的含义,主要就这几个参数verify-code
验证码,_time=1601308153790
时间戳(时间戳是一个记录时间的东西,用当前时间减去1970-01-01 08:00:00
即可得到,你可以通过这个工具时间戳在线转化,这里的1601308153790
所对应的时间为2020-09-28 23:58:06
)还有一个mobile=15212345678
,这个15212345678
是我刚刚输入的手机号。这是向服务器请求的数据,那在来看看服务器返回给我们的是什么
HTTP/1.1 200
Date: Mon, 28 Sep 2020 15:49:15 GMT
Content-Type: application/json;charset=UTF-8
Content-Length: 57
Connection: keep-alive
Set-Cookie: hyde_session=Kd10cra3X4yNBePaaQTKUkuYgX9J6Hfx_5337693
Set-Cookie: hyde_session_tm=1601308154470; Domain=.114yygh.com; Path=/; HttpOnly
Content-Security-Policy: : default-src *.114yygh.com *.qq.com *.baidu.com; font-src * data:
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
X-Via-JSL: d8c5e31,-
X-Cache: bypass
{"resCode":0,"msg":null,"data":{"endMilliseconds":59997}}
只需要关注最后一行即可,其中 resCode 为 0,同时手机号15212345678
也收到了验证码,貌似 resCode 为 0 就决定了服务器是否有给手机 号发送短信,事实上也是的,那么说了这么多,有什么用呢,用处可大了。
既然这样,我知道了发送上面的那个请求服务器就能给对应的手机号发送验证码,那么我能不能将上面那个请求的手机号给改一下,改成15287654321
,事实上是完全没问题的,这里我就放一张 HTTP 测试工具的截图。
那么是不是我多请求这样像服务器请求,我就能源源不断的收到验证码,现实很美好,人家服务器也不傻,我再一次向服务器发送请求,服务器给我的结果是
{"resCode":10000,"msg":"请58秒后重试","data":null}
没错,就需要等,而且这里的 resCode 也不为 0,那么既然要等一分钟的话,我能不能写个定时脚本,每隔一分钟发送一次,人家服务器也不傻,一般来说,一个手机号最多也就收 5 次验证码,多了就会提示明天再重试,或者今天收到的验证码过多等等。而外面的炸则是通过收集几百个这样的请求,然后将手机号替换成要轰炸的,即可实现多平台验证码轰炸一个手机号。
现在你可能已经知道了初步了解 HTTP 请求,但一般的网站都不会像这个这么简单的,明文标码,通常都会进行效验,例如图片验证码,滑块,点字,点图等等,并且还会进行加密操作处理,而这才算真正的难点。
POST 请求之登录
既然发验证码是这样,那如果是登录呢,下面就用网站 万创帮 为例,首先进入登录界面
输入手机号和密码,点击登录,同样的我们可以通过抓包工具获取到对应的 HTTP 请求,如下
POST https://m.wcbchina.com/api/login/login?rnd=0.6463111465399551 HTTP/1.1
Host: m.wcbchina.com
Connection: keep-alive
Content-Length: 149
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/javascript, */*; q=0.01
Origin: https://m.wcbchina.com
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Mobile Safari/537.36
Content-Type: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
{"auth":{"timestamp":1601312429287,"sign":"777473FB2A1838DBD64BA7A11C98911B"},"username":"15212345678","password":"E9BC0E13A8A16CBB07B175D92A113126"}
貌似比上面那个发验证码的复杂,确实,这是一个 POST 请求,你在链接上看不出什么有效信息,在最后一行才是关键。这里的timestamp
也就是时间戳,记录时间的,username 是我们输入的手机号(账号)没什么问题,这里的 sign 和 password 的内容又是啥?这就是加密,让你不能简单单纯的通过替换文本来实现登录,这就来分析一下他到底怎么加密的。
通过在浏览器按下 F12 键,打开控制台面板,接着点击 Network,这 里会将我们发送的请求记录下来
同时鼠标停在 Initiator 上有如下结果
不管三七二十一,点击跳转到对应的代码先,然后在左边下一个断点
这时候我们在点击登录按钮看看
没错,浏览器这时候停了下来,停在了我下断点的地方,通过函数名也可以猜到这个是发送的,对应的肯定在上面,通过右边的 Call Stack 函数调用栈即可追随上一函数
在这里我看到了原文的信息,这是通过 Jquery 通过 id 获取元素的值,也就是这里的手机号和密码,在这里还都是原文,点到下一个函数则变成了密文,那么肯定是上一个函数做了手脚。
认真观察,N 这个是我们的密码,但对 N 进行了一个操作也就是 a.hex_md5(N)
,没错,这就是 md5 加密。有关加密的可以看看我写过的 浅谈加密算法
那么通过加密工具将 md5 加密是否能得到我们要的加密结果,如下
E9BC0E13A8A16CBB07B175D92A113126
在看看 Password 的值,一模一样,看来已经解决了一个参数,那么还有一个sign