前端明文密钥+验证码逻辑缺失:一次SM4加密认证系统的暴力破解实战分析
字数 1920 2025-11-11 12:11:14

前端SM4加密认证系统安全漏洞分析与防御教学

一、漏洞概述

本教学文档基于对某业务系统登录模块的安全评估案例,详细分析前端SM4加密认证系统中存在的安全漏洞,包括前端硬编码密钥、验证码逻辑失效等问题,并给出完整的攻击复现方法和防御方案。

二、漏洞详细分析

2.1 前端加密逻辑完全暴露

漏洞发现过程

通过浏览器开发者工具分析前端Vue.js代码,定位到登录函数login()与加密模块efbb

关键代码分析

// 登录请求封装
Object(i["login"])({
    account: r.trim(),
    password: Object(c["encrypt"])(o),  // 密码经encrypt函数处理
    uuid: s,
    code: l
})

// 加密模块efbb
var i = n("8060").sm4;                  // 引入sm4库
var r = "E54CFxxxxxxxxxxxx99BE6C";      // 硬编码密钥!
function o(t) {
    return i.encrypt(t, r);             // 使用固定密钥加密
}

致命安全问题

  1. 密钥硬编码:SM4加密密钥E54CFxxxxxxxxxxxx99BE6C以明文形式写死在前端代码中
  2. 加密参数暴露:加密模式(ECB)、填充方式(PKCS7)、输出格式(Hex)均可通过逆向分析获取
  3. 加密流程可复现:攻击者可以完全重现前端加密逻辑,将任意明文密码转换为合法密文

2.2 验证码机制失效分析

请求包分析

{
    "account":"admin",
    "password":"582a14732cf52ab9e2ed853f3f9000de",
    "uuid":"",
    "code":""
}

验证码机制缺陷

  1. 后端校验缺失:服务器未对uuidcode字段进行有效性验证
  2. 绕过验证码:即使不触发验证码流程,也可直接提交登录请求
  3. 无防护措施:系统缺乏频率限制、失败锁定、IP封禁等安全机制

2.3 暴力破解攻击链构建

Step 1:复现SM4加密逻辑

使用Python复现前端SM4加密算法:

from sm4 import SM4Key

def sm4_encrypt(plaintext):
    key = SM4Key(b'E54CFxxxxxxxxxxxx99BE6C')
    ciphertext = key.encrypt(plaintext)
    return ciphertext.hex()

# 验证加密结果
result = sm4_encrypt("123456")
# 输出:582a14732cf52ab9e2ed853f3f9000de

Step 2:构建爆破字典并加密

  1. 收集常用密码字典(如rockyou.txt、弱口令字典)
  2. 使用复现的SM4加密逻辑对所有密码进行预处理加密
  3. 生成加密后的密码列表作为爆破载荷

Step 3:自动化爆破实施

使用Burp Suite Intruder模块进行自动化攻击:

攻击配置

  • 目标:POST /apiuser/usr/session/Login
  • 载荷位置{"account":"admin","password":"§payload§","uuid":"","code":""}
  • 载荷来源:预处理加密后的密码字典
  • 识别标志:响应体中"flag":true"token"字段

攻击结果

  • 数分钟内成功爆破出admin账户的正确密码
  • 获取JWT Token及用户上下文信息
  • 获得管理员权限后可进行横向渗透

三、漏洞利用扩展

3.1 权限提升与横向移动

  1. 系统内漏洞发现:获取管理员权限后发现任意文件上传、SQL注入等高危漏洞
  2. 用户规律分析:分析系统用户名命名规律(如工号、邮箱前缀等)
  3. 批量账户接管:利用相同技术批量爆破其他用户账户

3.2 攻击工具优化

  1. 多线程爆破:提高爆破效率
  2. 智能字典生成:基于目标特征生成针对性字典
  3. 代理轮换:避免IP被封禁

四、技术启示与防御建议

4.1 技术启示

1. 前端加密的安全误区

  • 错误认知:前端加密≠安全传输
  • 根本问题:客户端执行的任何加密逻辑都可能被逆向分析
  • 正确做法:敏感操作必须由服务端完成

2. 验证码机制的正确实现

  • 前后端联动:验证码必须前后端协同校验
  • 会话绑定uuidcode应在服务端绑定会话
  • 一次性使用:验证码使用后立即失效

3. 国密算法的正确使用

  • 算法误用:SM4等算法的错误使用反而增加安全风险
  • 规范遵循:需严格按照安全编码规范实施

4.2 具体防御措施

1. 密码传输安全改进

// 错误做法:前端加密
password: Object(c["encrypt"])(plainPassword)

// 正确做法:HTTPS传输 + 服务端哈希
password: plainPassword  // 通过HTTPS传输

服务端处理

  • 使用bcrypt、argon2等抗爆破哈希算法
  • 每个密码单独加盐处理
  • 实现安全的密码策略检查

2. 验证码机制强化

// 服务端验证逻辑
public boolean verifyCaptcha(String uuid, String code, HttpSession session) {
    // 检查参数非空
    if (StringUtils.isEmpty(uuid) || StringUtils.isEmpty(code)) {
        return false;
    }
    
    // 从会话中获取验证码信息
    CaptchaInfo captchaInfo = (CaptchaInfo) session.getAttribute("captcha_" + uuid);
    
    // 验证码存在性、有效性、一次性检查
    if (captchaInfo == null || !captchaInfo.isValid() 
        || !captchaInfo.getCode().equalsIgnoreCase(code)) {
        return false;
    }
    
    // 验证成功后立即失效
    session.removeAttribute("captcha_" + uuid);
    return true;
}

3. 登录防护策略

@Component
public class LoginSecurityService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public LoginResult attemptLogin(String username, String password, 
                                   String captchaUuid, String captchaCode) {
        
        // 1. 验证码校验
        if (!verifyCaptcha(captchaUuid, captchaCode)) {
            return LoginResult.fail("验证码错误");
        }
        
        // 2. 失败次数检查
        String failKey = "login_fail:" + username;
        Integer failCount = (Integer) redisTemplate.opsForValue().get(failKey);
        
        if (failCount != null && failCount >= 5) {
            // 账户锁定30分钟
            return LoginResult.fail("账户已锁定,请30分钟后重试");
        }
        
        // 3. IP频率限制
        String ipKey = "login_ip:" + getClientIP();
        Integer ipCount = (Integer) redisTemplate.opsForValue().get(ipKey);
        
        if (ipCount != null && ipCount >= 10) {
            // IP限流
            return LoginResult.fail("操作过于频繁,请稍后重试");
        }
        
        // 4. 实际身份验证
        User user = userService.findByUsername(username);
        if (user != null && passwordEncoder.matches(password, user.getPassword())) {
            // 登录成功,清除失败计数
            redisTemplate.delete(failKey);
            return LoginResult.success(generateToken(user));
        } else {
            // 登录失败,记录失败次数
            incrementFailureCount(failKey);
            incrementIPCount(ipKey);
            return LoginResult.fail("用户名或密码错误");
        }
    }
}

4. 动态密钥方案(如必须前端加密)

// 前端获取临时密钥
async function getTemporaryKey() {
    const response = await fetch('/api/get-encryption-key');
    const data = await response.json();
    
    // 密钥有时效性(如5分钟)
    return {
        key: data.key,
        expires: data.expires
    };
}

// 服务端密钥管理
@RestController
public class KeyController {
    
    @GetMapping("/api/get-encryption-key")
    public EncryptionKey getKey(HttpSession session) {
        String keyId = UUID.randomUUID().toString();
        String temporaryKey = generateRandomKey(); // 生成临时密钥
        
        // 存储密钥与会话关联
        redisTemplate.opsForValue().set("key_" + keyId, temporaryKey, 5, TimeUnit.MINUTES);
        
        return new EncryptionKey(keyId, temporaryKey, System.currentTimeMillis() + 300000);
    }
}

五、安全开发规范

5.1 前端安全规范

  1. 避免敏感信息硬编码:密钥、API凭证等必须从服务端动态获取
  2. 代码混淆保护:对关键业务逻辑进行代码混淆
  3. 最小化暴露原则:前端只处理必要的展示逻辑,业务逻辑交由服务端

5.2 服务端安全规范

  1. 输入验证:对所有输入参数进行严格验证
  2. 安全传输:强制使用HTTPS协议
  3. 防护机制:实现完善的频率限制、账户锁定等机制
  4. 日志监控:记录所有登录尝试,实时监控异常行为

5.3 加密算法使用规范

  1. 算法选择:使用经过验证的标准算法
  2. 参数配置:正确配置加密模式、填充方式等参数
  3. 密钥管理:实现安全的密钥生成、存储、轮换机制

六、总结

本案例揭示了"前端自欺式加密"的安全陷阱,强调了安全不是简单堆砌加密算法,而是构建端到端的可信链路。开发者必须牢记:客户端的一切皆可被控制,唯有服务端才是可信边界

通过本次分析,我们不仅了解了具体的攻击技术,更重要的是建立了完整的安全防护体系思维,为开发安全的认证系统提供了实践指导。


注:本教学文档基于真实安全评估案例,文中涉及的技术细节仅用于安全教育目的,在实际渗透测试中必须获得相关授权。

前端SM4加密认证系统安全漏洞分析与防御教学 一、漏洞概述 本教学文档基于对某业务系统登录模块的安全评估案例,详细分析前端SM4加密认证系统中存在的安全漏洞,包括前端硬编码密钥、验证码逻辑失效等问题,并给出完整的攻击复现方法和防御方案。 二、漏洞详细分析 2.1 前端加密逻辑完全暴露 漏洞发现过程 通过浏览器开发者工具分析前端Vue.js代码,定位到登录函数 login() 与加密模块 efbb 。 关键代码分析 致命安全问题 密钥硬编码 :SM4加密密钥 E54CFxxxxxxxxxxxx99BE6C 以明文形式写死在前端代码中 加密参数暴露 :加密模式(ECB)、填充方式(PKCS7)、输出格式(Hex)均可通过逆向分析获取 加密流程可复现 :攻击者可以完全重现前端加密逻辑,将任意明文密码转换为合法密文 2.2 验证码机制失效分析 请求包分析 验证码机制缺陷 后端校验缺失 :服务器未对 uuid 和 code 字段进行有效性验证 绕过验证码 :即使不触发验证码流程,也可直接提交登录请求 无防护措施 :系统缺乏频率限制、失败锁定、IP封禁等安全机制 2.3 暴力破解攻击链构建 Step 1:复现SM4加密逻辑 使用Python复现前端SM4加密算法: Step 2:构建爆破字典并加密 收集常用密码字典(如rockyou.txt、弱口令字典) 使用复现的SM4加密逻辑对所有密码进行预处理加密 生成加密后的密码列表作为爆破载荷 Step 3:自动化爆破实施 使用Burp Suite Intruder模块进行自动化攻击: 攻击配置 : 目标 :POST /apiuser/usr/session/Login 载荷位置 : {"account":"admin","password":"§payload§","uuid":"","code":""} 载荷来源 :预处理加密后的密码字典 识别标志 :响应体中 "flag":true 或 "token" 字段 攻击结果 : 数分钟内成功爆破出admin账户的正确密码 获取JWT Token及用户上下文信息 获得管理员权限后可进行横向渗透 三、漏洞利用扩展 3.1 权限提升与横向移动 系统内漏洞发现 :获取管理员权限后发现任意文件上传、SQL注入等高危漏洞 用户规律分析 :分析系统用户名命名规律(如工号、邮箱前缀等) 批量账户接管 :利用相同技术批量爆破其他用户账户 3.2 攻击工具优化 多线程爆破 :提高爆破效率 智能字典生成 :基于目标特征生成针对性字典 代理轮换 :避免IP被封禁 四、技术启示与防御建议 4.1 技术启示 1. 前端加密的安全误区 错误认知 :前端加密≠安全传输 根本问题 :客户端执行的任何加密逻辑都可能被逆向分析 正确做法 :敏感操作必须由服务端完成 2. 验证码机制的正确实现 前后端联动 :验证码必须前后端协同校验 会话绑定 : uuid 与 code 应在服务端绑定会话 一次性使用 :验证码使用后立即失效 3. 国密算法的正确使用 算法误用 :SM4等算法的错误使用反而增加安全风险 规范遵循 :需严格按照安全编码规范实施 4.2 具体防御措施 1. 密码传输安全改进 服务端处理 : 使用bcrypt、argon2等抗爆破哈希算法 每个密码单独加盐处理 实现安全的密码策略检查 2. 验证码机制强化 3. 登录防护策略 4. 动态密钥方案(如必须前端加密) 五、安全开发规范 5.1 前端安全规范 避免敏感信息硬编码 :密钥、API凭证等必须从服务端动态获取 代码混淆保护 :对关键业务逻辑进行代码混淆 最小化暴露原则 :前端只处理必要的展示逻辑,业务逻辑交由服务端 5.2 服务端安全规范 输入验证 :对所有输入参数进行严格验证 安全传输 :强制使用HTTPS协议 防护机制 :实现完善的频率限制、账户锁定等机制 日志监控 :记录所有登录尝试,实时监控异常行为 5.3 加密算法使用规范 算法选择 :使用经过验证的标准算法 参数配置 :正确配置加密模式、填充方式等参数 密钥管理 :实现安全的密钥生成、存储、轮换机制 六、总结 本案例揭示了"前端自欺式加密"的安全陷阱,强调了安全不是简单堆砌加密算法,而是构建端到端的可信链路。开发者必须牢记: 客户端的一切皆可被控制,唯有服务端才是可信边界 。 通过本次分析,我们不仅了解了具体的攻击技术,更重要的是建立了完整的安全防护体系思维,为开发安全的认证系统提供了实践指导。 注:本教学文档基于真实安全评估案例,文中涉及的技术细节仅用于安全教育目的,在实际渗透测试中必须获得相关授权。