影响版本如下:
Spark Core - Apache <=3.0.3
3.1.1 <= Spark Core - Apache <=3.1.2
3.2.0 <= Spark Core - Apache <=3.2.1
下载 Apache Spark 3.2.1
https://repo.huaweicloud.com/apache/spark/spark-3.2.1/spark-3.2.1-bin-hadoop2.7.tgz
漏洞触发的关键在于是否启用ACL,使用身份验证过滤器。启用ACL的方式:
1、通过设置选项 spark.acls.enable 启用 。
2、运行spark-shell时,通过-c(--conf)参数启动。
./spark-shell --conf spark.acls.enable=true
管理端:
spark-ui内置jetty处理http请求,并且使用 shade 打包方式修改了 jetty 包的前缀。rasp一般hook的jetty类全限定名称:
org.eclipse.jetty.server.Server
而 spark-ui中该类的名称
org.sparkproject.jetty.server.Server
对于这种场景,RASP必然丢失http参数。为了解决上面的问题,传统RASP需要修改代码,即:增加hook类、打包编译agent、重新发布、推动业务进程重启的流程(需要重启升级);而 jrasp 仅需要新增 hook 模块,无需重启业务,下发立即生效。
spark-jetty-hook 模块部分代码:
/**
* 1.重置绑定在线程上的线程本地变量,防止线程脏数据;
* 2.绑定本次请求信息;
* 3.如果请求逻辑没有走到这里,将出现脏数据
*/
public void jettyRequestPreHook() {
new EventWatchBuilder(moduleEventWatcher)
.onClass("org.sparkproject.jetty.server.Server")
.includeBootstrap()
.onBehavior("handle")
.withParameterTypes("org.sparkproject.jetty.server.HttpChannel")
.onWatch(new AdviceListener() {
@Override
public void before(Advice advice) throws Throwable {
if (!enableCheck) {
return;
}
// 清除上次请求的 requestInfo 信息,防止脏数据
requestInfoThreadLocal.remove();
// 绑定本次请求的请求头
Object httpChannel = advice.getParameterArray()[0];
if (httpChannel == null) {
return;
}
if (getRequest == null) {
getRequest = httpChannel.getClass().getMethod("getRequest");
}
Object httpRequest = ReflectUtils.invokeMethod(getRequest, httpChannel);
HashMap<String, Object> context = requestInfoThreadLocal.get();
// 俘虏HttpServletRequest参数为傀儡
final IHttpServletRequest httpServletRequest = puppet(IHttpServletRequest.class, httpRequest);
storeRequestInfo(context, httpServletRequest);
}
@Override
public void afterThrowing(Advice advice) throws Throwable {
// 代码执行异常情况清除 context 信息,防止内存泄漏
requestInfoThreadLocal.remove();
}
});
}
-----------------------------------------------------------------------
🔥🔥🔥国内技术领先的开源RASP社区 https://www.jrasp.com