RSA.js 前端加密逆向实战:3步定位智慧江财登录密码加密逻辑
当你在浏览器中输入账号密码点击登录时,那些看似简单的字符在传输前经历了怎样的蜕变?以江西财经大学智慧校园系统为例,其前端采用RSA非对称加密保护用户密码。本文将手把手带你用开发者工具解剖这套加密机制,掌握一套可复用的前端加密逆向分析方法。
1. 逆向分析前的准备工作
逆向工程如同侦探破案,需要先锁定"案发现场"。打开Chrome开发者工具(Windows快捷键F12,Mac快捷键Option+Command+I),我们主要使用以下功能模块:
- Network面板:记录所有网络请求,重点关注XHR和Doc类型
- Sources面板:查看和调试网页加载的所有JavaScript文件
- Console面板:实时执行JavaScript代码片段
- Elements面板:查看DOM结构和表单元素
首先访问智慧江财登录页,清空Network记录后执行一次登录操作。在Network面板的Filter输入login快速定位到登录请求,可以看到关键请求参数:
POST /cas/login HTTP/1.1 username=2202140875&password=7a8f9b3...<=_c4EC...&_eventId=submit关键观察点:
- password参数值明显不是明文(长度固定且为十六进制字符串)
- 存在lt等隐藏字段作为一次性令牌
- 请求头包含
Content-Type: application/x-www-form-urlencoded
2. 三步定位加密核心逻辑
2.1 全局搜索加密参数
在Sources面板按下Ctrl+Shift+F开启全局搜索,输入password或encrypt等关键词。很快在某个js文件中发现可疑代码片段:
function checkInput(){ var pwd = document.getElementById("password").value; var encPwd = rsaEncrypt(pwd); document.getElementById("passwordEnc").value = encPwd; return true; }这段代码揭示了加密流程:
- 获取明文密码输入
- 调用rsaEncrypt函数加密
- 将结果赋给隐藏表单字段passwordEnc
2.2 追踪加密函数实现
继续搜索rsaEncrypt函数定义,定位到核心加密逻辑:
function rsaEncrypt(text) { var rsa = new RSAKey(); rsa.setPublic( "5598e3b75d21a2989274e222fa59ab07d829faa29b544e3a920c4dd287aed9302a657280c23220a35ae985ba157400e0502ce8e44570a1513bf7146f372e9c842115fb1b86def80e2ecf9f8e7a586656d12b27529f487e55052e5c31d0836b2e8c01c011bca911d983b1541f20b7466c325b4e30b4a79652470e88135113c9d9", "10001" ); return rsa.encrypt(text); }关键参数说明:
n:RSA模数(Modulus),十六进制大整数e:公钥指数(Exponent),通常为65537(0x10001)encrypt():执行实际加密操作
2.3 验证加密结果
在Console面板直接调用加密函数验证:
rsaEncrypt("test123") // 输出:7a8f9b3d5e6c12a4f7...与Network中捕获的加密结果格式一致,确认这就是目标加密函数。
3. 深度解析RSA.js实现
通过进一步分析,发现系统使用了经典的RSA加密库组合:
| 文件 | 功能 | 依赖关系 |
|---|---|---|
| rsa.js | 核心RSA算法实现 | 依赖jsbn.js |
| jsbn.js | 大整数运算库 | 无依赖 |
| rng.js | 随机数生成器 | 依赖prng4.js |
| prng4.js | 伪随机数生成器实现 | 无依赖 |
加密调用链如下:
RSAKey()构造函数初始化密钥对象setPublic(n, e)设置公钥参数encrypt(text)执行PKCS#1 v1.5填充和模幂运算
典型加密流程代码:
// 初始化RSA实例 const rsa = new RSAKey(); // 设置公钥(实际项目这些参数可能需要动态获取) rsa.setPublic( "5598e3b75d21a2989274e222fa59ab07d829faa29b544e3a920c4dd287aed9302a657280c23220a35ae985ba157400e0502ce8e44570a1513bf7146f372e9c842115fb1b86def80e2ecf9f8e7a586656d12b27529f487e55052e5c31d0836b2e8c01c011bca911d983b1541f20b7466c325b4e30b4a79652470e88135113c9d9", "10001" ); // 加密密码 const encrypted = rsa.encrypt("myPassword123"); console.log(encrypted); // 输出加密结果4. 动态参数处理实战技巧
在实际逆向过程中,经常会遇到参数动态变化的情况。以下是几种常见场景的应对策略:
4.1 公钥参数动态获取
有时n/e参数会通过接口返回或写在页面元素中。可通过以下方式提取:
// 从页面元素获取 const n = document.querySelector("#rsaN").value; const e = document.querySelector("#rsaE").value; // 从接口响应获取(需Hook XMLHttpRequest或Fetch API) const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function() { this.addEventListener("load", function(){ if(this.responseURL.includes("getRSAKey")) { const data = JSON.parse(this.responseText); console.log("获取到RSA参数:", data.n, data.e); } }); return originalOpen.apply(this, arguments); };4.2 加密函数Hook技巧
当加密函数被混淆或难以定位时,可以Hook关键函数:
// 保存原始函数 const originalEncrypt = window.rsaEncrypt; // 重写函数 window.rsaEncrypt = function(text) { console.log("加密原文:", text); const result = originalEncrypt(text); console.log("加密结果:", result); return result; };4.3 自动化脚本示例
结合上述分析,可以编写自动登录脚本(Node.js示例):
const { RSAKey } = require("./rsa"); const axios = require("axios"); async function login(username, password) { // 第一步:获取登录页动态参数 const { data } = await axios.get("https://ssl.jxufe.edu.cn/cas/login"); const lt = parseLT(data); // 从HTML中提取lt参数 // 第二步:RSA加密密码 const rsa = new RSAKey(); rsa.setPublic( "5598e3b75d21a2989274e222fa59ab07d829faa29b544e3a920c4dd287aed9302a657280c23220a35ae985ba157400e0502ce8e44570a1513bf7146f372e9c842115fb1b86def80e2ecf9f8e7a586656d12b27529f487e55052e5c31d0836b2e8c01c011bca911d983b1541f20b7466c325b4e30b4a79652470e88135113c9d9", "10001" ); const encPassword = rsa.encrypt(password); // 第三步:提交登录 const params = new URLSearchParams(); params.append("username", username); params.append("password", encPassword); params.append("lt", lt); params.append("_eventId", "submit"); const response = await axios.post("https://ssl.jxufe.edu.cn/cas/login", params); console.log("登录结果:", response.data); } function parseLT(html) { // 实现从HTML中提取lt参数的逻辑 return html.match(/name="lt" value="([^"]+)"/)[1]; }逆向分析前端加密就像解谜游戏,关键在于找到正确的线索入口。通过本文介绍的三步法——抓包定位、全局搜索、参数追踪,配合开发者工具的灵活使用,可以系统性地破解大多数网站的前端加密逻辑。