不多说废话,直接进入正题
在验证界面按 F12 进入开发者模式
随便输入一个密码,抓一下校验请求
抓到了一个向 https://ai.aifengkeji.com/h5pwd/check.aspx 发起的 POST 请求,那么这个就是它的校验请求了,直接看它的调用栈
很明显,这是个 Vue 项目,所以逻辑大概率就在 app.js 里了,直接在 JS 里搜一下请求的 URL路径
在 JS 内搜到了如下片段
- checkPwd: function() {
- var t = this;
- return Object(s["a"])(regeneratorRuntime.mark((function e() {
- var n, i, a;
- return regeneratorRuntime.wrap((function(e) {
- while (1)
- switch (e.prev = e.next) {
- case 0:
- return n = t,
- e.next = 3,
- t.$http.post("/h5pwd/check.aspx", {
- pwd: t.pwd
- });
- case 3:
- if (i = e.sent,
- 200 == i.status) {
- e.next = 7;
- break
- }
- return t.$dialog.alert({
- title: "系统提示",
- message: "访问密码错误,请到新有趣工具箱小程序或者在微信公众号艾锋降级回复密码,查看访问密码。",
- theme: "round-button",
- showCancelButton: !0,
- confirmButtonText: "前往"
- }).then((function() {
- n.gotoMiniProgram()
- }
- )),
- e.abrupt("return");
- case 7:
- a = new Date,
- localStorage.setItem("pwd_date", "".concat(a.getFullYear(), "/").concat(a.getMonth(), "/").concat(a.getDate())),
- t.getNotify(),
- t.$toast("欢迎使用"),
- t.showInputPwd = !1;
- case 12:
- case "end":
- return e.stop()
- }
- }
- ), e)
- }
- )))()
- },
复制代码 这个 checkPwd 方法,它将用户输入的密码(t.pwd)作为参数,向服务器的/h5pwd/check.aspx 接口发送一个 POST 请求。
随后,程序会根据服务器返回的 HTTP 状态码进行判断:
既然这段验证机制的核心在于 “成功后在本地存储中留下一个 pwd_date 的凭证”,那么我们完全可以手动将这个本地凭证写入浏览器,在控制台执行
- localStorage.setItem("pwd_date", [new Date().getFullYear(), new Date().getMonth(), new Date().getDate()].join('/'));
复制代码
执行后刷新即可实现绕过
按理来说,到这里应该就结束了
然而,在寻找 check.aspx 验证接口的 JavaScript 代码时,意外发现了 H5 密码机制中另一条相关联的 URL 路径:/h5pwd/req
这段代码定义了 create 方法,这个方法首先检查本地的 t.pwd ,如果已经有密码存在,则提示“请勿重复生成”。如果密码不存在,程序则会向 /h5pwd/req 接口发起 GET 请求,请求服务器生成一个新的访问密码。
那么问题就来了,我是怎么知道这是负责生成密码的?
我们可以看到该方法被命名为 create(译:生成),并且内部请求的接口路径是 /h5pwd/req。在计算机中,req 通常是 Request 的简写,而结合 create 这个动作,我们可以合理推断出:这个方法负责向服务器请求生成一个新的访问密码。
并且在这段逻辑片段的上方,我们定位到了渲染标记 [t._v("有趣工具箱密码生成器"])]。证据确凿,那么这个 JS 必定负责生成密码
我们将这个 URL 路径和 https://ai.aifengkeji.com/ 拼接起来访问,直接测试接口。
接口成功返回了生成的新的密码。测试一下这个密码是否可以通过
验证
成功通过
至此,我们对该网站访问密码机制的分析已完整结束。
回顾整个过程,我们所有的"突破",都来自于对客户端状态的掌控。无论是用一行代码在 localStorage 里注入 pwd_date 登录状态,还是通过一个简单的 GET 请求就获取到最新的访问密码,这些都指向同一个事实:网站将它的安全判断,委托给了我们能轻易接触和修改的前端环境。
|