Flink目录穿越漏洞浅析(CVE-2020-17519)
茜さす 漏洞分析 7348浏览 · 2021-01-11 07:45

简介

Apache Flink 1.11.0-1.11.2中引入的一项更改,允许攻击者通过JobManager进程的REST接口读取本地文件系统上的任何文件,访问仅限于JobManager进程可访问的文件。

复现

下载源码:

git clone https://github.com/apache/flink.git

根据官方公告可以得到修复的commitb561010b0ee741543c3953306037f00d7a9f0801

里边还有测试用例可以去看看。

使用未打补丁的parent-commit搭建环境。

git checkout 7fed9f0243aaf80d0060f075b95ba46b3207c8a8

编译

mvn clean package -DskipTests

一般半小时就行

编译后会出现build-target目录,修改配置文件用于IDEA-DEBUG动态调试

flink-debug-src/build-target/conf/flink-conf.yaml

IDEA调试配置

在配置文件最后添加:

env.java.opts: -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5006

开启服务

flink-debug-src/build-target/bin/start-cluster.sh

POC

http://localhost:8081/jobmanager/logs/..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252fetc%252fpasswd

分析

从路由处开始分析。

org.apache.flink.runtime.rest.handler.router.Router#route(org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpMethod, java.lang.String, java.util.Map<java.lang.String,java.util.List<java.lang.String>>)

跟踪POC的path部分,POC的后半部分是双URL编码的,到达服务器自动解码一次,第二次解码处理发生在decodePathTokens函数。

org.apache.flink.runtime.rest.handler.router.Router#decodePathTokens

对path使用/进行分割,然后得到三个元素,接着遍历三个元素使用QueryStringDecoder.decodeComponent进行URL解码并返回包含穿越目录的tokens

org.apache.flink.runtime.rest.handler.router.MethodlessRouter#route

routes.entrySet()进行循环遍历

然后和前面的pathTokens进行匹配判断,跟进pattern.match

org.apache.flink.runtime.rest.handler.router.PathPattern#match

遍历并判断key是否:开头,然后将../../../../../../../../../../../../etc/passwd放进Map中并返回ture

org.apache.flink.runtime.rest.handler.router.RouteResult#RouteResult

在上层中通过if判断,并将Map作为参数穿个RouteResult实例化。

org.apache.flink.runtime.rest.handler.router.RouterHandler#routed

实例化的RouteResult对象又作为参数传入RoutedRequest对象。

org.apache.flink.runtime.rest.handler.router.RoutedRequest#RoutedRequest

最终的RoutedRequest对象成员如下:

org/apache/flink/runtime/rest/handler/AbstractHandler.java:161

层层跟进至关键创建HandlerRequest对象的部分,跟进构造参数routedRequest.getRouteResult().pathParams()

org.apache.flink.runtime.rest.handler.router.RoutedRequest#getRouteResult

org.apache.flink.runtime.rest.handler.router.RouteResult#pathParams

结果为包含目录穿越的MAP

org.apache.flink.runtime.rest.handler.HandlerRequest#HandlerRequest(R, M, java.util.Map<java.lang.String,java.lang.String>, java.util.Map<java.lang.String,java.util.List<java.lang.String>>, java.util.Collection<java.io.File>)

Map中取出目录穿越的POC,然后传入resolveFromString

org.apache.flink.runtime.rest.messages.MessageParameter#resolveFromString

最终放入MessageParameter对象的value成员中,接着将MessageParameter对象放入以class为键的MAP中。

实例化后的HandlerRequest对象成员为:

org/apache/flink/runtime/rest/handler/AbstractHandler.java:179

HandlerRequest对象又作为参数传入respondToRequest函数

org.apache.flink.runtime.rest.handler.cluster.AbstractJobManagerFileHandler#respondToRequest

HandlerRequest对象又传入getFile函数。

org.apache.flink.runtime.rest.handler.cluster.JobManagerCustomLogHandler#getFile

org.apache.flink.runtime.rest.handler.HandlerRequest#getPathParameter

取出../../../../../../../../../../../../etc/passwd然后用于创建File对象,最后在HandlerUtils.transferFile中读取文件对象并作为响应返回。

参考

https://mp.weixin.qq.com/s/ZsNOKC8ulVk66BZZxqD-BA

https://lists.apache.org/thread.html/r6843202556a6d0bce9607ebc02e303f68fc88e9038235598bde3b50d%40%3Cdev.flink.apache.org%3E

1 条评论
某人
表情
可输入 255
目录