快速定位前端加密方法与密钥指南

 2025-03-28    0 条评论    44 浏览 JavaScript Hook

目录

  • 常见前端加密场景
  • 定位加密方法的技术
  • 寻找密钥和盐的方法
  • 常用工具
  • 案例分析
  • 防御措施

常见前端加密场景

前端加密通常用于以下几个场景:

  • 登录密码加密传输
  • API 参数签名
  • 敏感信息传输
  • 防止接口被直接调用
  • Token 生成与验证
  • 定位加密方法的技术
1. 断点调试法

最直接有效的方法是通过 Chrome DevTools 进行断点调试:

// 给常见加密函数设置断点
debug(CryptoJS.AES.encrypt);  // 如果使用了 CryptoJS 库
debug(md5);                   // 如果使用了 MD5
debug(encodeURIComponent);    // URL 编码
debug(btoa);                  // Base64 编码

操作步骤:

  • 在可能的触发点(如表单提交、按钮点击)设置事件断点
  • 在 Network 面板找到目标请求,查看加密参数
  • 在网页中触发该操作,断点会在加密函数执行时停止
2. 函数重写拦截法
// 拦截常见加密函数
(function() {
  // 保存原始函数
  const originalMD5 = window.md5;
  
  // 重写函数
  window.md5 = function() {
    console.log('MD5 调用参数:', arguments);
    console.trace('MD5 调用堆栈');
    return originalMD5.apply(this, arguments);
  };
})();

这种方法可以应用于常见的加密库函数:

// 针对 CryptoJS
if (window.CryptoJS) {
  const originalAES = CryptoJS.AES.encrypt;
  CryptoJS.AES.encrypt = function() {
    console.log('AES 加密参数:', arguments);
    console.log('密钥:', arguments[1].toString());
    return originalAES.apply(this, arguments);
  };
}
3. 全局函数监控法
// 监控所有可能的加密函数
const potentialEncryptionFuncs = [
  'encrypt', 'decrypt', 'encode', 'decode', 'hash', 
  'md5', 'sha1', 'sha256', 'aes', 'des', 'rsa'
];

function monitorFunctions(obj, path = '') {
  if (!obj || typeof obj !== 'object') return;
  
  Object.keys(obj).forEach(key => {
    const currentPath = path ? `${path}.${key}` : key;
    
    if (typeof obj[key] === 'function' && 
        potentialEncryptionFuncs.some(funcName => 
          key.toLowerCase().includes(funcName))) {
      
      const original = obj[key];
      obj[key] = function() {
        console.log(`可能的加密函数被调用: ${currentPath}`, arguments);
        return original.apply(this, arguments);
      };
    }
    
    if (obj[key] && typeof obj[key] === 'object') {
      monitorFunctions(obj[key], currentPath);
    }
  });
}

monitorFunctions(window);
4. 网络请求拦截法
// 拦截所有请求
const originalFetch = window.fetch;
window.fetch = async function() {
  const url = arguments[0];
  const options = arguments[1] || {};
  
  console.log('Fetch 请求:', {
    url,
    method: options.method || 'GET',
    headers: options.headers,
    body: options.body
  });
  
  // 尝试解析请求体,寻找加密参数
  if (options.body) {
    try {
      const bodyJson = JSON.parse(options.body);
      Object.keys(bodyJson).forEach(key => {
        if (typeof bodyJson[key] === 'string' && bodyJson[key].length > 20) {
          console.log(`可能的加密参数: ${key}`, bodyJson[key]);
        }
      });
    } catch (e) {}
  }
  
  return originalFetch.apply(this, arguments);
};

寻找密钥和盐的方法

1. 静态代码分析

查找特征字符串:

// 在控制台执行,搜索可能的密钥
(function findKeys() {
  const htmlSource = document.documentElement.outerHTML;
  
  // 常见密钥、盐的命名模式
  const patterns = [
    /['"]?(?:key|salt|secret|iv|token|nonce)['"]?\s*[:=]\s*['"]([^'"]{8,})['"]/, 
    /['"]?(?:aes|des|encryption|crypto)(?:Key|Salt|Iv)['"]?\s*[:=]\s*['"]([^'"]{8,})['"]/, 
    /const\s+(?:KEY|SALT|IV|SECRET)\s*=\s*['"]([^'"]{8,})['"]/
  ];
  
  patterns.forEach(pattern => {
    const matches = htmlSource.match(new RegExp(pattern, 'gi'));
    if (matches) {
      console.log('找到可能的密钥:', matches);
    }
  });
})();
2. 动态参数监控
// 监控加密函数的参数
function monitorEncryptionParams() {
  const suspectFuncs = [
    {obj: window.CryptoJS?.AES, method: 'encrypt'},
    {obj: window.CryptoJS?.DES, method: 'encrypt'},
    {obj: window, method: 'btoa'},
    {obj: window, method: 'md5'},
    // 添加其他可能的加密函数
  ];
  
  suspectFuncs.forEach(({obj, method}) => {
    if (obj && typeof obj[method] === 'function') {
      const original = obj[method];
      obj[method] = function() {
        console.log(`${method} 调用:`, {
          args: [...arguments],
          possibleKey: arguments[1]?.toString?.() || arguments[1]
        });
        return original.apply(this, arguments);
      };
    }
  });
}

monitorEncryptionParams();
3. 本地存储检查
// 检查localStorage和sessionStorage中的可能密钥
function checkStorageForKeys() {
  const keyPatterns = [
    /key/i, /salt/i, /secret/i, /token/i, /iv/i, /nonce/i, /sign/i, /crypto/i
  ];
  
  console.log('检查 localStorage:');
  Object.keys(localStorage).forEach(key => {
    if (keyPatterns.some(pattern => pattern.test(key))) {
      console.log(`可能的密钥 (localStorage): ${key} = ${localStorage.getItem(key)}`);
    }
  });
  
  console.log('检查 sessionStorage:');
  Object.keys(sessionStorage).forEach(key => {
    if (keyPatterns.some(pattern => pattern.test(key))) {
      console.log(`可能的密钥 (sessionStorage): ${key} = ${sessionStorage.getItem(key)}`);
    }
  });
}

checkStorageForKeys();
4. Cookie 检查
// 检查Cookie中的可能密钥
function checkCookiesForKeys() {
  const keyPatterns = [
    /key/i, /salt/i, /secret/i, /token/i, /iv/i, /nonce/i, /sign/i, /crypto/i
  ];
  
  document.cookie.split(';').forEach(cookie => {
    const [name, value] = cookie.trim().split('=');
    if (keyPatterns.some(pattern => pattern.test(name))) {
      console.log(`可能的密钥 (Cookie): ${name} = ${value}`);
    }
  });
}

checkCookiesForKeys();
常用工具
  • Chrome DevTools - 断点调试、网络请求分析
  • Fiddler/Charles - HTTP抓包分析
  • JavaScript Deobfuscator - 反混淆加密代码
  • Crypto Detective - 检测加密算法特征
  • CyberChef - 在线加解密工具

案例分析

RSA加密定位案例

很多网站使用RSA对密码加密,可以通过以下方式定位:

// 监控 JSEncrypt 库
if (window.JSEncrypt) {
  const originalEncrypt = window.JSEncrypt.prototype.encrypt;
  window.JSEncrypt.prototype.encrypt = function(data) {
    console.log('RSA 加密数据:', data);
    console.log('RSA 公钥:', this.getPublicKey());
    return originalEncrypt.call(this, data);
  };
  
  const originalSetPublicKey = window.JSEncrypt.prototype.setPublicKey;
  window.JSEncrypt.prototype.setPublicKey = function(key) {
    console.log('设置 RSA 公钥:', key);
    return originalSetPublicKey.call(this, key);
  };
}
AES加密定位案例
// 监控 CryptoJS AES
if (window.CryptoJS && window.CryptoJS.AES) {
  const originalEncrypt = window.CryptoJS.AES.encrypt;
  window.CryptoJS.AES.encrypt = function(message, key, cfg) {
    console.log('AES 加密信息:', {
      原文: message.toString(),
      密钥: key.toString(),
      配置: cfg
    });
    return originalEncrypt.apply(this, arguments);
  };
}

防御措施

作为开发者,如何避免前端加密被轻易破解:
  • 不要只依赖前端加密 - 始终在服务器端进行密码验证
  • 使用HTTPS - 加密传输所有数据
  • 混淆和代码保护 - 增加逆向难度
  • 动态密钥 - 每次请求使用不同的密钥
  • 服务器验证 - 关键业务逻辑放在服务器端