利用CoreDNS枚举集群Service & Port & 解决方案

本文为技术探讨文章,文中只提供思路,并不提供攻击脚本。

0. 关于云原生渗透

在新型网络架构当中,云原生可以说是新型应用部署方式的一颗明星,很多公司都在积极的建设自己的云原生体系,在云原生体系的建设当中,云原生安全是至关重要的,而提到了云原生安全那就不得不提云原生渗透了。

并不是所有的云原生渗透都能通过简单的容器逃逸来进行,在对单一容器的渗透进行不下去的时候,选择结束渗透是很不明智的选择,因为除了无安全隐患的容器,集群内还可能存在有安全隐患且符合逃逸条件的容器,这样就涉及到容器之间的横向攻击了。在基础的K8s集群当中,并不能使用ICMP协议进行容器发现,例如下图:

所以如何进行容器发现成了云原生渗透的一个难题。

1. 发现

  1. 早些时间在看CoreDNS代码的过程中,发现在/pkg/dnsutil/reverse.go存在关于in-addr.arpa的定义。

跟了一下,走到 /plugin/hosts/hosts.go ,发现CoreDNS是支持PTR解析记录的。

看下k8s_external包,这个包是处理svc域名的一些操作。109行发现K8s插件也是支持ptr记录的,CoreDNS的使用过程是集群内部的域名,coreDNS分发至kubedns,集群外的域名则通过coreDNS进行递归。

2. 利用

在公共DNS服务器上,很少会有ip存在PTR解析记录,而集群内部所有的域名都是通过Service进行管理,这样也就说明,如果CoreDNS的K8s插件若支持PTR记录,那么集群内部就可以通过ip来获取svc域名:

正常情况下,查询一个service的A记录是这样的:

复制代码
<SVC>.<NAMESPACE>.svc.cluster.local

若PTR可用,我们将会得到重要的三个信息,一个是命名空间、一个是svc名称、一个就是svcip,事实证明,这条路可行。

那么按照这个思路,就可以通过PTR记录进行所有的Service的枚举了。

3. 实现

在集群容器内部,由于需要使用CoreDNS,/etc/resolv.conf文件会与普通的机器不同:

由于K8s配置过程中需要将CoreDNS与svc放在同一个网段,这样一来,通过容器内部的**/etc/resolv.conf**文件就可以知道集群svc所在ip段,通过Fuzz这个段所有的ip将会得到完整的svc情况。

根据这个原理,写了个脚本,去跑所有svc地址。

一个B段6000并发下仅需要几秒。

4. 端口探测

以上的所有操作是将所有的svc名字、命名空间以及ip地址枚举了出来,但是在svc当中还有一个重要信息,那就是端口,其实按照上文描述的方法已经可以对存活svc进行端口扫描了,但是就这么做的话,不优雅,因此再次打开CoreDNS的代码,找找优雅的办法。

/plugin/k8s_external/external.go 107行

这是允许通过的四种dns类型,A为 域名-ip4;AAAA为 域名-ip6;PTR为 ip-域名;SRV为 服务-端口。

前三种已经都被我们所利用了,唯独第四种SRV记录还没被使用。

SRV记录

英语:Service Record ,中文又名服务定位记录是域名系统中用于指定服务器提供服务的位置(如主机名和端口)数据。此数据于RFC 2782中定义,类型代码为33。部分协议,如会话发起协议(SIP)及可扩展消息与存在协议(XMPP)通常需要服务记录的支持。

正常使用是这样的:

复制代码
nslookup -qt=srv _<service>._<proxy>.domain.com

在集群当中测试下:

按照这个写法不行,但是代码中写了,说明肯定是支持的,把svc、命名空间、协议进行排列组合,看哪一种是可行的。最终发现,集群内的srv域名查询需要符合以下格式。

复制代码
nslookup -qt=srv <svc>.<namespace>.svc.cluster.local

其中30111端口的,即为svc开放端口。

将这个东西融入之前的脚本,达到如下效果。

复制代码
{"default":[{"SVC":"kubernetes","IP":"10.1.0.1","Port":[443]}],"kube-system":[{"SVC":"kube-dns","IP":"10.1.0.10","Port":[9153,53]}],"moresec-system":[{"SVC":"****-fileserver","IP":"10.1.3.195","Port":[7777]},{"SVC":"******","IP":"10.1.8.79","Port":[6379]},{"SVC":"*****-****-service","IP":"10.1.12.127","Port":[443]},{"SVC":"*****-********","IP":"10.1.53.252","Port":[27017]},{"SVC":"*******-*****-manager","IP":"10.1.1.43","Port":[5020]},{"SVC":"******-********","IP":"10.1.59.129","Port":[8010,5006]},{"SVC":"*******-******","IP":"10.1.56.115","Port":[8090]},{"SVC":"***-*******","IP":"10.1.72.216","Port":[***]},{"SVC":"*****-******-manager-proxy","IP":"10.1.88.58","Port":[8080]},{"SVC":"******-******","IP":"10.1.92.117","Port":[9001,9000]},{"SVC":"******-*****-srv","IP":"10.1.95.161","Port":[5002]},{"SVC":"******-scanner","IP":"10.1.139.11","Port":[5103]},{"SVC":"****-*****-******","IP":"10.1.213.112","Port":[8080]},{"SVC":"*****-*****","IP":"10.1.222.32","Port":[5040]},{"SVC":"******-*****","IP":"10.1.245.240","Port":[443]},{"SVC":"******-*****","IP":"10.1.255.210","Port":[4151,4150]}],"work":[{"SVC":"tomcat8","IP":"10.1.229.92","Port":[80]}],"zhuri":[{"SVC":"tp-svc","IP":"10.1.0.47","Port":[15443]},{"SVC":"tomcat-svc","IP":"10.1.34.246","Port":[9080]},{"SVC":"baota-svc","IP":"10.1.47.228","Port":[18800,18080,18888]},{"SVC":"sqli-svc","IP":"10.1.224.165","Port":[18081]}]}

这样就优雅了很多。但是值得一提的是,这个方法拉出的port不区分tcp udp,但是就我使用过的几个集群来讲,除了CoreDNS以外,很少会有udp端口的出现,但具体情况根据集群业务来看。

5. 解决

对于业务不需要srv与ptr记录的集群,禁用coreDNS的ptr与srv记录。

复制代码
#修改CoreDNS的配置文件
kubectl edit configmap/coredns -n kube-system

加入如下两句配置:

经过该配置,CoreDNS会拦截掉ptr与srv记录。

相关推荐
飞函安全14 分钟前
Mattermost限制历史消息访问:开源软件商业化困局
运维·安全·开源软件
飞Link18 分钟前
【开发工具】Docker常用操作
运维·docker·容器
运维行者_1 小时前
网络流量分析入门:从流量监控与 netflow 看懂核心作用
运维·开发语言·网络·云原生·容器·kubernetes·php
hanyi_qwe1 小时前
Docker 容器操作 【docker (二)】
docker·容器·eureka
小白电脑技术1 小时前
简单点!异地访问Docker的方式简单点!
docker·容器·电脑
Zhen (Evan) Wang1 小时前
Docker 完整安装 Redis
redis·docker·容器
专业开发者1 小时前
蓝牙智能体温监测解决方案助力学校安全复课
安全
小趴菜不能喝1 小时前
Docker Swarm
运维·docker·容器
同聘云1 小时前
阿里云国际站服务器防御怎么做?服务器能做什么用途?
服务器·安全·阿里云·云计算