声明

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

逆向目标

  • 目标:某政务服务网登录接口

  • 主页:aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbG9naW4vaW5kZXg=

  • 接口:aHR0cHM6Ly9sb2dpbi5obnp3ZncuZ292LmNuL3RhY3MtdWMvbmF0dXJhbE1hbi9sb2dpbk5v

  • 逆向参数:

    Form Data:loginNo、loginPwd、code、requestUUID

    Request Headers:token

抓包分析

本次逆向目标来源于某位粉丝的求助:

随便输入账号密码点击登陆,抓包发现接口的 Request Headers 有个加密参数 token,Form Data 里 loginNo、loginPwd、code、requestUUID 都是经过加密处理了的,loginNo 和 loginPwd 应该就是用户名密码了,由于登录前需要过一下滑动验证码,因此可以猜测另外两个参数与验证码有关,不过仅从抓包来看,另外两个参数类似于 uuid 的格式,不太像验证码的参数。

另外可以注意到登陆前,有两次 csrfSave 和一次 verCode 的请求,正常请求成功就会返回一个 JSON,里面有个 data 参数,后面应该是会用到的。

参数逆向

Form Data

先看 Form Data,搜索任意一个参数,比如 loginNo,很容易在 login.js 里找到加密的地方,用户名和密码都经过了 encrypt 这个函数进行加密,backUrl 这个值,是利用 localStorage 属性,从浏览器储存的键值对的数据里取的,为空也不影响。

跟进 encrypt,可以看到用到了 JSEncrypt,标准的 RSA 加密:

再看看 loginCode,直接搜索这个值,可以看到是 verCode 这个请求返回的:

然后再看看 requestUUID,其值就是个 UUID,直接在当前文件(login.js)里搜索,可以看到定义的地方,有个 uploadUUID() 方法,就是在设置 UUID 的值,方法里面是向一个 uploadIdentifier 的接口发送了 post 请求:

这里注意,如果你直接全局搜索 UUID 的话,还可以在 common.js 里搜索到一个方法,经过测试,直接使用这个方法生成一个 uuid 也是可以请求通过的,这网站可能不严谨,不会严格检测这个值。

Request Headers

Form Data 解决了,再来看看 Request Headers 里的 token 参数,由于它存在于请求头里,所以我们可以通过 Hook 的方式来查找其生成的地方:

(function () {
var org = window.XMLHttpRequest.prototype.setRequestHeader;
window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
if (key == 'token') {
debugger;
}
return org.apply(this, arguments);
};
})();

这里我们也可以直接搜索 token、setRequestHeader 之类的关键字,很容易在 common.js 里找到,当我们点击登陆,会有一个 csrfSave 的请求,返回的 data 值,经过 encrypt 方法加密后就是登陆请求头的 token 了。

这个 token 参数在很多请求中都会用到,生成方法是一样的,都是拿 csrfSave 请求返回的 data 经过 RSA 加密后得到的:

另外注意一点的就是,以上所有涉及到网络请求的,Cookie 都需要一个 SESSION 值,这个可以在首次访问页面获取到:

登陆流程

这里我们理一下登陆的流程:

  1. 访问首页拿 Cookie 中的 SESSION 值;
  2. 访问 csrfSave,拿到一个 data 值,经过 RSA 加密得到 token,携带 token 访问 uploadIdentifier,拿到 uuid;
  3. 访问 csrfSave,拿到一个 data 值,经过 RSA 加密得到 token,携带 token 访问 verCode,拿到 code;
  4. 访问 csrfSave,拿到一个 data 值,经过 RSA 加密得到 token,携带 token、uuid、code 和加密后的账号密码,访问 loginNo 登录。

这里第2步,也可以直接用 Python 或者 JS 生成一个 uuid,网站校验不严格,也可以通过,另外可以看出这个滑块是假的,通过代码可以无视滑块进行登录。

完整代码

GitHub 关注 K 哥爬虫,持续分享爬虫相关代码!欢迎 star !https://github.com/kgepachong/

以下只演示部分关键代码,不能直接运行! 完整代码仓库地址:https://github.com/kgepachong/crawler/

JavaScript 加密代码

/* ==================================
# @Time : 2022-01-11
# @Author : 微信公众号:K哥爬虫
# @FileName: encrypt.js
# @Software: PyCharm
# ================================== */ JSEncrypt = require("jsencrypt") function encrypt(pwd){
var key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsgDq4OqxuEisnk2F0EJFmw4xKa5IrcqEYHvqxPs2CHEg2kolhfWA2SjNuGAHxyDDE5MLtOvzuXjBx/5YJtc9zj2xR/0moesS+Vi/xtG1tkVaTCba+TV+Y5C61iyr3FGqr+KOD4/XECu0Xky1W9ZmmaFADmZi7+6gO9wjgVpU9aLcBcw/loHOeJrCqjp7pA98hRJRY+MML8MK15mnC4ebooOva+mJlstW6t/1lghR8WNV8cocxgcHHuXBxgns2MlACQbSdJ8c6Z3RQeRZBzyjfey6JCCfbEKouVrWIUuPphBL3OANfgp0B+QG31bapvePTfXU48TYK0M5kE+8LgbbWQIDAQAB";
var encrypt = new JSEncrypt();
encrypt.setPublicKey(key);
var encrypted = encrypt.encrypt(pwd);
return encrypted;
} // 测试样例
// console.log(encrypt("15555555555"))

Python 登录代码

# ==================================
# @Time : 2022-01-11
# @Author : 微信公众号:K哥爬虫
# @FileName: hnzww_login.py
# @Software: PyCharm
# ================================== import execjs
import requests cookies = {}
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36" with open("encrypt.js", encoding="utf-8") as f:
js = execjs.compile(f.read()) def csrf_save():
url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
headers = {"User-Agent": UA}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
data = response["data"]
return data def get_session():
url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
headers = {"User-Agent": UA}
response = requests.get(url=url, headers=headers)
cookies.update(response.cookies.get_dict()) def get_uuid():
url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
uuid = response["data"]
return uuid def ver_code():
url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
response = requests.post(url=url, headers=headers, cookies=cookies).json()
data = response["data"]
return data def login(phone, pwd, code, uuid):
url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"User-Agent": UA,
"token": js.call("encrypt", csrf_save())
}
data = {
"backUrl": "",
"loginNo": js.call("encrypt", phone),
"loginPwd": js.call("encrypt", pwd),
"code": code,
"requestUUID": uuid,
"guoBanAuthCode": ""
}
response = requests.post(url=url, headers=headers, cookies=cookies, data=data)
print(response.json()) def main():
phone = input("请输入账号:")
pwd = input("请输入密码:")
get_session()
uuid = get_uuid()
code = ver_code()
login(phone, pwd, code, uuid) if __name__ == '__main__':
main()

【JS 逆向百例】HN某服务网登录逆向,验证码形同虚设的更多相关文章

  1. Java使用正则表达式取网页中的一段内容(以取Js方法为例)

    关于正则表达式: 表1.常用的元字符 代码 说明 . 匹配除换行符以外的任意字符 \w 匹配字母或数字或下划线或汉字 \s 匹配任意的空白符 \d 匹配数字 \b 匹配单词的开始或结束 ^ 匹配字符串 ...

  2. 【算法】C语言趣味程序设计编程百例精解

    C语言趣味程序设计编程百例精解 C/C++语言经典.实用.趣味程序设计编程百例精解(1)  https://wenku.baidu.com/view/b9f683c08bd63186bcebbc3c. ...

  3. node.js 初学(二)—— 搭建注册/登录服务器

    node.js 初学(二)—— 搭建注册/登录服务器 理论上来说,代码实现在理论和实际上是一样的.但实际上来说,他们不是 做一个最简单的用户注册登录功能 1.接口定义: 注册:/user?act=re ...

  4. 20155327李百乾《网络对抗》逆向及Bof基础

    20155327李百乾<网络对抗>逆向及Bof基础 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任 ...

  5. Java设计模式百例 - 观察者模式

    观察者(Observer)模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,主体对象的状态变化会通知所有观察者对象.观察者模式又叫做发布-订阅(Publish/Subscribe ...

  6. node.js+express+jade系列五:ajax登录

    本文通过jquery实现简单的无刷新登录 1:首先要在router中配置登录请求,因为登录需要传user和pwd考虑到安全需用post请求 {        path:'/',        meth ...

  7. 上百例Silverlight网站及演示汇总,供友参考

    毁灭2012 博客园 首页 新闻 新随笔 联系 管理 订阅 随笔- 125  文章- 0  评论- 446  上百例Silverlight网站及演示汇总,供友参考   今天我将发现的Silverlig ...

  8. 本页面用来演示如何通过JS SDK,创建完整的QQ登录流程,并调用openapi接口

    QQ登录将用户信息存储在cookie中,命名为__qc__k ,请不要占用 __qc__k : 1) :: 在页面顶部引入JS SDK库: 将“js?”后面的appid参数(示例代码中的:100229 ...

  9. Java模拟登录带验证码的教务系统(原理详解)

    一:原理 客户端访问服务器,服务器通过Session对象记录会话,服务器可以指定一个唯一的session ID作为cookie来代表每个客户端,用来识别这个客户端接下来的请求. 我们通过Chrome浏 ...

  10. .NET Core实战项目之CMS 第十六章 用户登录及验证码功能实现

    前面为了方便我们只是简单实现了基本业务功能的增删改查,但是登录功能还没有实现,而登录又是系统所必须的,得益于 ASP.NET Core的可扩展性因此我们很容易实现我们的登录功能.今天我将带着大家一起来 ...

随机推荐

  1. appuploder全过程使用教程(Windows版本)

    转载:使用appuploader工具流程(Windows版本) 一.登录apple官网,注册账号 1.注册苹果账号 Sign In - Apple 2.登录开发者中心 ,出现协议弹框,同意即可. 二. ...

  2. PPT 商务PPT怎么做

    商务报告:公司专属PPT模板怎么做? 通过LOGO 提取主色调 搜集相关元素 通过LOGO 提取主色调 搜集相关元素 下载图片使用 建立版面

  3. Kubernetes(K8S) Pod 介绍

    Pod 是 k8s 系统中可以创建和管理的最小单元, 是资源对象模型中由用户创建或部署的最小资源对象模型, 也是在 k8s 上运行容器化应用的资源对象, 其他的资源对象都是用来支撑或者扩展 Pod 对 ...

  4. Java SpringBoot FTP 上传下载文件

    POM 添加依赖 <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all< ...

  5. 【3rd_Party】format() 处理一些常见的格式化解决方案

    fmt的痛与对format设计的思考 fmt:轻量高性能的C++格式化库 C++20 引入了新的 format() 函数,该函数以字符串形式返回参数的格式化表示.format() 使用 python ...

  6. SpringBoot 学习笔记:运维篇

    SpringBoot程序的打包和运行 开发部门使用Git.SVN等版本控制工具上传工程到版本服务器 服务器使用版本控制工具下载工程 服务器上使用Maven工具在当前真机环境下重新构建项目 启动服务 程 ...

  7. Serverless 年终技术盘点 :工业、学术、社区遍地开花,国内厂商迅速卡位

    作者 | 刘宇(花名:江昱) ​ 2021 年,Serverless 架构在权威咨询机构 Forrester 所发布的 < The Forrester Wave: Function-As-A-S ...

  8. d3过滤

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  9. freeswitch on centos docker

    概述 freeswitch是一款简单好用的VOIP开源软交换平台. centos7 docker上编译安装fs的流程记录. 环境 docker engine:Version 24.0.6 centos ...

  10. JavaScriptif while for switch流程控制 JS函数 内置对象

    1,if else语句 2,if else if else语句 3,switch语句 4,for循环 5,while循环 6,三元运算 7,JS中的函数 8,JS中的匿名函数 9,JS中的立即执行函数 ...