JS逆向—某登录接口加密逻辑逆向分析测试

admin 2026-05-24 04:57:20 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文对某自助管理平台登录接口进行JS逆向分析,发现其采用AES-128-ECB模式对密码进行前端加密,但密钥硬编码于JS中且使用ECB弱模式,存在高危安全风险。文章详细还原了加密流程、CryptoJS模块加载链,并通过Node.js成功复现,最后给出改用非对称加密、CBC/GCM模式及加强验证码机制等安全建议。 综合评分: 88 文章分类: web安全,逆向分析,漏洞分析,安全开发


cover_image

JS逆向 — 某登录接口加密逻辑逆向分析测试

原创

yushao yushao

逆向有你

2026年5月23日 00:00 河南

在小说阅读器读本章

去阅读

有需要测试的APK、网页可以私聊,说出详细的需求即可,有时间就会回复

共同学习,vx:ivu123ivu

#


1. 测试概述

| 项目 | 内容 | | — | — | | 测试目标 | 某自助管理平台登录接口前端加密逻辑分析 | | 测试类型 | 前端加密算法逆向分析 / 黑盒接口测试 | | 测试时间 | 2026-05-22 | | 测试环境 | Windows 10 / Chrome 148 / Node.js | | 测试方法 | Chrome DevTools 静态分析 + 动态验证 |


2. 目标页面结构分析

2.1 登录表单结构

通过页面分析,登录表单包含以下关键字段:

| 字段 | Element ID | 表单名 | 类型 | 说明 | | — | — | — | — | — | | 产品服务码 | #codename | codeName | text | 明文提交 | | 服务码口令 | #codepass | 无 | password | 用户输入,不直接提交 | | 加密密码 | #codepass2 | codePwd | hidden | 加密后实际提交值 | | 验证码 | #randcode | codeNum | text | 明文提交 |

表单 action 地址为 rmiloginSSP.action,方法为 POST

关键发现:服务码口令存在”明文输入框 + 隐藏域”的双框架设计,明文密码不直接进入表单,加密结果写入隐藏域后再提交。

2.2 验证码机制

GET /randPic.action?login=true
GET /randPic.action?id={Math.random()}&login=true  # 点击刷新时

每次刷新验证码使用随机数作为缓存破坏参数,无防重放机制。


3. 前端 JS 资源分析

3.1 加密相关 JS 文件加载顺序

页面按以下顺序引入加密依赖,加载链条完整,属于标准的 CryptoJS 分模块加载方式:

core.js          → CryptoJS 核心运行时
enc-base64.js    → Base64 编解码
md5.js           → MD5 哈希(EvpKDF 依赖项)
evpkdf.js        → OpenSSL EVP_BytesToKey 密钥派生
cipher-core.js   → 分组密码抽象基类
mode-ecb.js      → ECB 工作模式
aes.js           → AES 算法实现

所有文件最后修改时间均为 2024-04-01,版本固定,无动态更新机制。

3.2 JS 文件模块格式说明

上述文件均使用 UMD(Universal Module Definition) 规范,其加载逻辑为:

if (typeof exports === "object") {
    module.exports = factory(require("./core")); // Node.js CommonJS 路径
} else {
    factory(root.CryptoJS); // 浏览器全局对象路径
}

在浏览器中,CryptoJS 会挂载到 window 全局对象,各模块依次扩展该对象。但在 Node.js 中必须通过 require() 显式引入,否则会抛出 ReferenceError: CryptoJS is not defined


4. 加密逻辑逆向分析

4.1 加密函数原文(页面内联脚本)

在页面 HTML 内联脚本中提取到完整的加密函数:

function encrypt(word) {
    if (!word) {
        return;
    }
    var key = CryptoJS.enc.Utf8.parse("****************");  // 已脱敏
    var srcs = CryptoJS.enc.Utf8.parse(word);
    var encrypted = CryptoJS.AES.encrypt(srcs, key, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.toString();
}

提交逻辑:

function onSubmit() {
    if (displayWarn()) {
        var pwd = $("#codepass").val();
        if (pwd) {
            $("#codepass2").val(encrypt(pwd));  // 加密后写入隐藏域
        }
        $("#serviceCodeForm").submit();
        return true;
    }
    return false;
}

4.2 加密参数汇总

| 参数 | 值 | 备注 | | — | — | — | | 算法 | AES-128 | 密钥长度 128 bit | | 工作模式 | ECB | 不使用 IV | | 填充方式 | PKCS7(等同 PKCS#5) | 标准填充 | | 密钥 | 硬编码 16 字节固定值 | 已脱敏 | | 密钥编码 | UTF-8 | | | 明文编码 | UTF-8 | | | 密文输出 | Base64 字符串 | |

4.3 加密流程图

用户输入明文密码
       │
       ▼
CryptoJS.enc.Utf8.parse(word)     ← 明文转 WordArray
       │
       ▼
CryptoJS.AES.encrypt(srcs, key,   ← AES-128-ECB-PKCS7 加密
  { mode: ECB, padding: Pkcs7 })
       │
       ▼
encrypted.toString()              ← WordArray 转 Base64
       │
       ▼
写入 #codepass2 隐藏域
       │
       ▼
POST rmiloginSSP.action (codePwd=Base64密文)

5. 验证与复现

5.1 使用 Node.js 内置 crypto 模块(成功)

改用 Node.js 原生 crypto 模块实现等价逻辑,零外部依赖:

const crypto = require("crypto");

function encrypt(word) {
    if (!word) return;
    const key = Buffer.from("****************", "utf8");  // 已脱敏
    const cipher = crypto.createCipheriv("aes-128-ecb", key, null);
    cipher.setAutoPadding(true);  // 等同 PKCS7
    const encrypted = Buffer.concat([cipher.update(word, "utf8"), cipher.final()]);
    return encrypted.toString("base64");
}

console.log(encrypt("测试密码"));  // 已脱敏

5.2 验证结果

使用测试账号的服务码口令执行加密,将输出结果与浏览器实际提交的 codePwd 参数值进行比对:

| 项目 | 结果 | | — | — | | 算法复现 | ✅ 成功 | | 与浏览器输出一致性 | ✅ 完全一致(字节级匹配) | | Node.js 运行状态 | ✅ 正常退出,无报错 |


6. 安全风险评估

6.1 发现的安全问题

风险一:加密密钥硬编码在前端(高危)

密钥以明文形式直接写在页面内联 JavaScript 中,任何人打开浏览器开发者工具即可获取。这导致 AES 加密的保护意义基本失效——攻击者拿到密钥后可在本地完整复现加密过程,绕过前端校验直接构造请求。

风险二:使用 ECB 工作模式(中危)

ECB(Electronic Codebook)模式对相同的明文块始终产生相同的密文块,不使用 IV(初始向量)。这意味着:

  • • 相同密码每次加密结果完全相同,存在重放攻击风险
  • • 密文不具备语义安全性

推荐替换为 CBC 或 GCM 模式,并配合随机 IV。

风险三:前端加密不等于传输安全(低危,注意事项)

此处的加密行为属于”应用层加密”,其安全性完全依赖于外层 HTTPS 的传输加密。若 HTTPS 配置得当,这层加密提供的额外保护有限;但若 HTTPS 被中间人剥离,前端加密也无法抵御,因为攻击者可以直接修改 JS 代码。

6.2 风险汇总

| 编号 | 风险描述 | 等级 | 建议 | | — | — | — | — | | R-01 | AES 密钥硬编码于前端 JS | 高危 | 改为服务端动态下发一次性密钥,或使用非对称加密(RSA/ECDH) | | R-02 | 使用 ECB 加密模式 | 中危 | 改用 CBC/GCM 模式,服务端生成随机 IV 随接口下发 | | R-03 | 验证码无防重放机制 | 低危 | 验证码与 Session 强绑定,一次性使用后立即失效 |


7. 总结

本次分析通过 Chrome DevTools 对目标平台的登录接口进行了完整的前端加密逻辑逆向,成功还原了密码加密的算法、参数与流程,并在本地通过代码验证与浏览器实际行为完全一致。

核心结论:该平台登录密码采用 AES-128 ECB PKCS7 + Base64 方式进行前端加密处理,但由于密钥硬编码在前端代码中,且使用了安全性较弱的 ECB 模式,整体加密方案存在可被轻易逆向的风险,建议研发团队结合上述安全建议进行改进。


本报告仅用于安全研究与技术学习目的,相关测试均在合法授权范围内进行。

·今 日 推 荐·

| | | | — | — | | | |


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:逆向有你 yushao yushao《JS逆向 — 某登录接口加密逻辑逆向分析测试》

评论:0   参与:  0