开放签电子签章系统审计
字数 1841 2025-10-01 14:05:44

电子签章系统安全审计教学:开放签漏洞分析与挖掘

1. 项目概述

开放签是一个电子签章平台,提供完整的电子签约解决方案,主要功能包括:

  • 合同创建、签署、管理及验证
  • 个人与企业实名认证
  • 电子印章管理
  • 合同模板配置
  • 签署流程控制

系统入口

  • 网页版登录界面:需通过实际环境获取
  • 登录后台:需通过实际环境获取
  • 企业管理后台:需通过实际环境获取
  • FOFA查询:可通过网络空间测绘平台搜索相关资产

2. 鉴权机制分析

2.1 技术栈识别

系统采用Shiro框架作为权限控制核心,配置文件位于项目配置文件中。

2.2 白名单配置

Shiro配置中存在多个白名单接口,需要重点关注:

  • 检查白名单路由是否包含敏感信息或功能
  • 分析是否有不必要的接口被暴露

2.3 JWT过滤器实现

系统注册了JwtFilter,拦截所有路由请求,关键实现逻辑:

public class JwtFilter extends AuthenticatingFilter {
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        // 自动调用executeLogin方法处理凭据
        return executeLogin(request, response);
    }
    
    // 实际登录逻辑
    protected boolean executeLogin(ServletRequest request, ServletResponse response) {
        // 从请求头或参数获取token
        String token = getToken(request);
        JwtToken jwtToken = new JwtToken(token);
        
        // Shiro主题登录验证
        getSubject(request, response).login(jwtToken);
        return true;
    }
}

2.4 认证流程分析

  1. Token获取:从请求头或参数中提取JWT token
  2. Realm处理:调用ShiroRealm.doGetAuthenticationInfo()方法
  3. Token验证
    • 第126行:调用checkUserTokenIsEffect校验token有效性
    • 第145行:使用JwtUtil.getUsername()解密token获取用户名
    • 第152行:根据用户名查询数据库获取用户信息
    • 第170行:使用JwtUtil.verify()方法根据用户名和查询到的密码进行token校验

2.5 JWT实现缺陷

// JWT验证逻辑问题
public boolean verify(String token, String username, String password) {
    // 使用用户密码生成JWT密钥
    String secret = generateSecret(password);
    // 用此密钥验证token
    // ...
}

安全问题:JWT密钥基于用户密码生成,这意味着攻击者如果已获取密码,可直接登录系统,降低了JWT的安全价值。

3. 任意文件上传漏洞

3.1 漏洞位置

文件FileStorageController.java
方法create()

3.2 漏洞分析

@PostMapping("/create")
public Result create(@RequestParam("file") MultipartFile file) {
    // 获取文件原始后缀
    String originalExtension = getOriginalExtension(file);
    // 获取文件类型
    String fileType = getFileType(file);
    // 生成新文件名:UUID + 原始后缀
    String newFileName = generateUUID() + originalExtension;
    
    // 调用存储服务保存文件
    iAnnexStorageService.create(file, newFileName);
    return Result.ok().data("uid", newFileName);
}

3.3 存储实现分析

系统支持三种存储方式:

  1. 阿里云OSS存储
  2. 本地存储
  3. MinIO存储

本地存储实现(重点风险点):

public class LocalStorageService implements StorageService {
    public void store(InputStream inputStream, String fileName) {
        // 直接使用Files工具类写入文件
        Files.copy(inputStream, Paths.get(storagePath, fileName));
    }
}

存储路径:需查看配置文件确定具体存储位置

3.4 利用限制

  • 上传后仅返回文件UID,不返回完整路径
  • 需要结合其他漏洞获取文件访问路径
  • 实际利用难度较高但仍存在风险

4. 用户信息泄露漏洞

4.1 权限控制机制

系统采用注解形式进行权限控制,未配置权限注解的接口可能存在越权访问风险。

4.2 未授权接口发现

漏洞位置1SysUserController.java中的getAllUsers方法

// 缺少权限注解
@GetMapping("/all")
public Result<List<SysUser>> getAllUsers() {
    // 使用MyBatis-Plus自动生成查询
    List<SysUser> users = sysUserService.list();
    return Result.ok().data(users);
}

泄露数据:用户ID、注册账号(手机号)

验证请求

GET /sys/user/all

漏洞位置2SysUserController.java中的userInfo方法

// 缺少权限注解
@GetMapping("/info/{id}")
public Result<SysUser> userInfo(@PathVariable String id) {
    // 通过ID查询用户信息
    SysUser user = sysUserService.getById(id);
    return Result.ok().data(user);
}

泄露数据:完整用户信息

验证请求

GET /sys/user/info/{userId}

4.3 攻击链构建

  1. 通过/all接口获取所有用户ID和手机号
  2. 使用获取的ID调用/info/{id}接口获取完整用户信息
  3. 收集敏感信息进行进一步攻击

5. 审计方法与技巧总结

5.1 鉴权审计要点

  1. Shiro配置审计

    • 检查白名单接口合理性
    • 验证自定义Filter的安全性
  2. JWT实现审计

    • 检查密钥生成算法
    • 验证token验证逻辑是否与用户敏感信息耦合

5.2 文件上传审计要点

  1. 文件后缀处理:是否仅使用原始后缀而未做安全过滤
  2. 存储方式:本地存储直接写入文件系统风险最高
  3. 回显信息:是否暴露文件存储路径

5.3 权限控制审计要点

  1. 注解缺失检查:查找未配置权限注解的接口
  2. 默认权限:检查新注册用户的默认权限分配
  3. 接口参数:验证基于ID的参数是否存在越权

5.4 自动化辅助工具

  1. 代码扫描:使用SAST工具搜索特定关键词(如MultipartFile@GetMapping
  2. 接口遍历:使用Burp Suite等工具遍历所有接口检测未授权访问
  3. 依赖检查:检查使用的框架版本是否存在已知漏洞

6. 修复建议

  1. JWT安全增强

    • 使用独立于用户密码的JWT密钥
    • 增加token过期时间和刷新机制
  2. 文件上传修复

    • 限制上传文件类型
    • 对上传文件重命名并隐藏存储路径
    • 设置文件服务器隔离环境
  3. 权限控制修复

    • 为所有敏感接口添加权限注解
    • 实施基于角色的访问控制(RBAC)
    • 添加接口级权限验证
  4. 敏感信息保护

    • 对返回的用户信息进行脱敏处理
    • 实施最小权限原则,仅返回必要信息

通过本教学文档,安全研究人员可以深入了解电子签章系统的安全审计方法,掌握常见漏洞的挖掘技巧和修复方案。

电子签章系统安全审计教学:开放签漏洞分析与挖掘 1. 项目概述 开放签是一个电子签章平台,提供完整的电子签约解决方案,主要功能包括: 合同创建、签署、管理及验证 个人与企业实名认证 电子印章管理 合同模板配置 签署流程控制 系统入口 : 网页版登录界面:需通过实际环境获取 登录后台:需通过实际环境获取 企业管理后台:需通过实际环境获取 FOFA查询:可通过网络空间测绘平台搜索相关资产 2. 鉴权机制分析 2.1 技术栈识别 系统采用 Shiro框架 作为权限控制核心,配置文件位于项目配置文件中。 2.2 白名单配置 Shiro配置中存在多个白名单接口,需要重点关注: 检查白名单路由是否包含敏感信息或功能 分析是否有不必要的接口被暴露 2.3 JWT过滤器实现 系统注册了 JwtFilter ,拦截所有路由请求,关键实现逻辑: 2.4 认证流程分析 Token获取 :从请求头或参数中提取JWT token Realm处理 :调用 ShiroRealm.doGetAuthenticationInfo() 方法 Token验证 : 第126行:调用 checkUserTokenIsEffect 校验token有效性 第145行:使用 JwtUtil.getUsername() 解密token获取用户名 第152行:根据用户名查询数据库获取用户信息 第170行:使用 JwtUtil.verify() 方法根据用户名和查询到的密码进行token校验 2.5 JWT实现缺陷 安全问题 :JWT密钥基于用户密码生成,这意味着攻击者如果已获取密码,可直接登录系统,降低了JWT的安全价值。 3. 任意文件上传漏洞 3.1 漏洞位置 文件 : FileStorageController.java 方法 : create() 3.2 漏洞分析 3.3 存储实现分析 系统支持三种存储方式: 阿里云OSS存储 本地存储 MinIO存储 本地存储实现 (重点风险点): 存储路径 :需查看配置文件确定具体存储位置 3.4 利用限制 上传后仅返回文件UID,不返回完整路径 需要结合其他漏洞获取文件访问路径 实际利用难度较高但仍存在风险 4. 用户信息泄露漏洞 4.1 权限控制机制 系统采用 注解形式 进行权限控制,未配置权限注解的接口可能存在越权访问风险。 4.2 未授权接口发现 漏洞位置1 : SysUserController.java 中的 getAllUsers 方法 泄露数据 :用户ID、注册账号(手机号) 验证请求 : 漏洞位置2 : SysUserController.java 中的 userInfo 方法 泄露数据 :完整用户信息 验证请求 : 4.3 攻击链构建 通过 /all 接口获取所有用户ID和手机号 使用获取的ID调用 /info/{id} 接口获取完整用户信息 收集敏感信息进行进一步攻击 5. 审计方法与技巧总结 5.1 鉴权审计要点 Shiro配置审计 : 检查白名单接口合理性 验证自定义Filter的安全性 JWT实现审计 : 检查密钥生成算法 验证token验证逻辑是否与用户敏感信息耦合 5.2 文件上传审计要点 文件后缀处理 :是否仅使用原始后缀而未做安全过滤 存储方式 :本地存储直接写入文件系统风险最高 回显信息 :是否暴露文件存储路径 5.3 权限控制审计要点 注解缺失检查 :查找未配置权限注解的接口 默认权限 :检查新注册用户的默认权限分配 接口参数 :验证基于ID的参数是否存在越权 5.4 自动化辅助工具 代码扫描 :使用SAST工具搜索特定关键词(如 MultipartFile 、 @GetMapping ) 接口遍历 :使用Burp Suite等工具遍历所有接口检测未授权访问 依赖检查 :检查使用的框架版本是否存在已知漏洞 6. 修复建议 JWT安全增强 : 使用独立于用户密码的JWT密钥 增加token过期时间和刷新机制 文件上传修复 : 限制上传文件类型 对上传文件重命名并隐藏存储路径 设置文件服务器隔离环境 权限控制修复 : 为所有敏感接口添加权限注解 实施基于角色的访问控制(RBAC) 添加接口级权限验证 敏感信息保护 : 对返回的用户信息进行脱敏处理 实施最小权限原则,仅返回必要信息 通过本教学文档,安全研究人员可以深入了解电子签章系统的安全审计方法,掌握常见漏洞的挖掘技巧和修复方案。