IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Hadoop Yarn RPC未授权访问漏洞简单复现

    sky发表于 2021-11-22 11:13:00
    love 0

    前段时间看到了阿里云发的一篇文章,捕获到了某挖矿软件利用Hadoop Yarn的RPC接口进行执行命令。

    上周有空看了下,在java中可以很简单的使用yarnClient调用RPC接口进行通信,其实就是之前的Hadoop Yarn REST API未授权访问漏洞变成,由REST API变成了RPC接口,REST API的默认端口为8088,RPC的默认端口为8032。

    整个执行命令的通信过程分为两步 :

    这个过程中会发送不少RPC包

    1. 请求APPID
    2. 提交执行任务

    在网上找了一个使用yarnClient获取信息的代码(https://blog.csdn.net/jsbylibo/article/details/109286147),

    package com.**.dfp.rtsync.task;
     
    import lombok.extern.slf4j.Slf4j;
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.yarn.api.records.ApplicationReport;
    import org.apache.hadoop.yarn.api.records.YarnApplicationState;
    import org.apache.hadoop.yarn.client.api.YarnClient;
    import org.apache.hadoop.yarn.conf.YarnConfiguration;
    import org.apache.hadoop.yarn.exceptions.YarnException;
     
    import java.io.IOException;
    import java.util.EnumSet;
    import java.util.List;
     
    /**
     * Description
     *
     * @author Bob
     * @date 2020/10/22
     **/
    @Slf4j
    public class YarnTest {
        public static void main(String[] args){
            Configuration conf = new YarnConfiguration();
            YarnClient yarnClient = YarnClient.createYarnClient();
            yarnClient.init(conf);
            yarnClient.start();
            try {
                //查询运行状态所有任务
                List<ApplicationReport> applicationReportList = yarnClient.getApplications(EnumSet.of(YarnApplicationState.RUNNING));
                for (ApplicationReport applicationReport : applicationReportList) {
                    // 获取Name
                    String name = applicationReport.getName();
                    // 获取ApplicationType
                    String applicationType = applicationReport.getApplicationType();
                    ApplicationId applicationId;
                    log.info("-----------applicationId:{},name:{},quene:{},user:{},type:{}", applicationReport.getApplicationId(), applicationReport.getName(), applicationReport.getQueue(), applicationReport.getUser(), applicationReport.getApplicationType());
                    // 检查是否实时集成任务(Apache Spark)
                    if (name.equals(applicationName)) {
                        if ("Apache Spark".equalsIgnoreCase(applicationType) || "Spark".equalsIgnoreCase(applicationType)) {
                            // ApplicationId
                            applicationId = applicationReport.getApplicationId();
                            // Kill applicationId
                            //yarnClient.killApplication(applicationId);
                            log.info("==========applicationId:{} is killed!", applicationName);
                            break;
                        } else {
                            log.warn("The app {} is not valid spark job! ", applicationName);
                        }
                    }
                }
            } catch (YarnException | IOException e) {
                log.error("kill killYarnApplication error:", e);
                throw new BusinessException("停止Yarn任务失败!");
            } finally {
                if (yarnClient != null) {
                    try {
                        // 停止YarnClient
                        yarnClient.stop();
                        // 关闭YarnClient
                        yarnClient.close();
                    } catch (IOException e) {
                        log.error("关闭Yarn Client失败!", e);
                    }
                }
            }
        }
    }

    简单改造后就可以变成执行命令的JAVA代码:



沪ICP备19023445号-2号
友情链接