Red Hat JBoss EAP RichFaces - unserialize + el = RCE - 【CVE-2018-14667】
字数 1735 2025-08-22 18:37:15
Red Hat JBoss EAP RichFaces 反序列化漏洞分析 (CVE-2018-14667)
漏洞概述
CVE-2018-14667 是 Red Hat JBoss EAP 中 RichFaces 框架的一个远程代码执行漏洞,评级为"Critical"。该漏洞允许未经身份验证的攻击者通过发送特制的对象(包含恶意表达式)来绕过白名单保护,触发反序列化操作,最终导致任意Java代码执行。
漏洞环境
- 测试环境:
- Tomcat 8.5.24
- JDK 1.8.144
- richfaces-demo-3.3.0.GA-tomcat6.war
漏洞触发流程
-
入口点 - BaseFilter#doFilter
- 请求通过JBoss SeamFilter → Ajax4jsfFilter → BaseFilter
- 关键判断逻辑决定是否进入InternetResourceService
-
核心处理 - InternetResourceService#serviceResource
- 从URL获取resourceKey
- 通过ResourceBuilderImpl获取resource和resourceDataForKey
- 根据条件调用resource.getLastModified、resource.getExpired或resource.send
-
反序列化绕过 - ResourceBuilderImpl
- 对URL中的数据进行base64解码和zip解压缩
- 使用LookAheadObjectInputStream进行反序列化,但有白名单限制
- 白名单检查resource-serialization.properties文件
-
资源生成 - ResourceBuilderImpl
- 从URL路径生成resource
- 使用UserResource类(在白名单中)作为反序列化载体
-
EL表达式注入 - UserResource
- 反序列化后的UriData对象中的表达式会被解析
- 通过getLastModified、getExpired或send方法触发表达式执行
漏洞利用分析
关键利用点
-
UserResource.UriData 类:
- 包含createContent、value、modified和expires字段
- 这些字段可以包含EL表达式
-
表达式执行触发点:
- getLastModified() - 解析modified字段
- getExpired() - 解析expires字段
- send() - 解析createContent字段
-
反序列化控制:
- 通过/DATA/路径后的base64编码数据控制反序列化内容
- 数据经过base64解码和zip解压缩
利用条件
- 目标系统使用了RichFaces 3.x至3.3.4版本
- 系统中包含a4j:mediaOutput标签的页面
- 能够获取到mediaOutput生成的资源路径
漏洞复现步骤
-
获取资源路径:
- 访问包含a4j:mediaOutput标签的页面
- 从响应中提取src属性值(如:/DATA/eAHF...jsf)
-
构造恶意payload:
- 使用提供的POC生成代码
- 替换其中的EL表达式为恶意代码
- 生成base64编码的压缩payload
-
发送恶意请求:
- 使用获取的资源路径前半部分
- 拼接生成的恶意payload
- 发送到目标服务器
POC生成代码分析
import com.sun.facelets.el.TagMethodExpression;
import com.sun.facelets.el.TagValueExpression;
// ... 其他import省略
public class Main {
public static void main(String[] args) throws Exception {
// 1. 设置恶意EL表达式
String pocEL = "#{request.getClass().getClassLoader().loadClass(\"java.lang.Runtime\").getMethod(\"getRuntime\").invoke(null).exec(\"calc\")}";
// 2. 修改MethodExpression的serialVersionUID(适配Tomcat 8.5.24)
// ... 反射修改代码省略
// 3. 构造createContent MethodExpression
MethodExpressionImpl mei = new MethodExpressionImpl(pocEL, null, null, null, null, new Class[]{OutputStream.class, Object.class});
// ... 包装过程省略
// 4. 构造modified和expires表达式
// ... 构造过程省略
// 5. 创建恶意UriData对象
UserResource.UriData uriData = new UserResource.UriData();
// 通过反射设置各字段
// 6. 序列化并编码payload
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(uriData);
// ... 压缩和base64编码过程省略
// 7. 生成最终payload
String poc = "/DATA/" + new String(dataArray, "ISO-8859-1") + ".jsf";
System.out.println(poc);
}
}
漏洞修复建议
- 升级到RichFaces 3.3.4以上版本
- 禁用不必要的RichFaces功能
- 加强输入验证和过滤
- 限制反序列化操作
技术要点总结
-
反序列化绕过:
- 利用UserResource类在白名单中的特性
- 通过合法的类载体携带恶意数据
-
EL表达式注入:
- 利用RichFaces对EL表达式的自动解析特性
- 通过反序列化控制表达式内容
-
触发链设计:
- 利用mediaOutput标签的自动资源生成机制
- 通过标准接口(getLastModified等)触发表达式解析
-
兼容性处理:
- 解决不同容器中MethodExpression的serialVersionUID差异
- 确保payload在不同环境中的稳定性
参考
- CVE-2018-14667
- RichFaces官方公告
- RF-13977漏洞报告