# 利用 Nebula 实现红队基础设施安全性
# 前言
本文的全部内容均建立在 “红队团队服务器应该是本地的,位于可以物理访问且可以控制其他人能否物理访问它的位置” 这一理论之上。由于红队的团队服务器作为整个渗透攻击的中心服务器,上面存储着大量的敏感数据,将其托管在云上存在一定的风险。
Tim MalcomVetter 在其博客的 “Safe Red Team Infrastructure” 一文中对如何建立安全的红队运营网络进行了高级概述。
这是来自 Tim MalcomVetter 博客文章中的架构图。我们将使用它作为参考,完成红队基础设施安全性的实现与改进。
# 服务器配置
为了实现 Nebula 网络的搭建,除了本地的团队服务器外还需要准备至少两台拥有公网 IP 的服务器(例如云服务器),出于安全和便捷的考虑,我们需要使用 SSH 密钥来连接至这两台服务器。
在本地的团队服务器上创建一个 SSH 密钥对并绑定至实例,生成的私钥不要保存在任何云上,任何身份验证 / 加密材料都应存储在本地。这包括制作的密钥对以及 Nebula 的证书。
或者直接通过云创建 SSH 密钥并绑定至实例。
测试下能否成功连接到云服务器。注意,如果 Linux 的 SSH 客户端使用 pem 格式私钥连接到服务端的话,需要修改 pem 文件权限为 400。
# 安装 Nebula
Nebula 是制作网状覆盖 VPN 的一种极其简单的方法,只要它们可以到达中间主机,网络上的任何两点都可以进行通信。
# 本地团队服务器端
在本地团队服务器上下载并解压 Nebula。
mkdir nebula && cd nebula
wget https://github.com/slackhq/nebula/releases/download/v1.6.1/nebula-linux-amd64.tar.gz
tar -xvf nebula-linux-amd64.tar.gz
# 监听站(Listeningpost)
仅开放 SSH 端口且限定其来源为我使用的 IP,后面需要时再开启其他端口。
安装后面需要用到的 socat 和 Nebula。
sudo apt-get update -y && sudo apt-get install socat
wget https://github.com/slackhq/nebula/releases/download/v1.6.1/nebula-linux-amd64.tar.gz
tar -xvf nebula-linux-amd64.tar.gz
# 中间服务器 - 灯塔(Lighthouse)
Nebula 不是传统的中心辐射型 VPN。它是一个网状覆盖 VPN,其中任何两点都可以直接通信,只要它们都能找到 Nebula 网络的焦点,即称为灯塔(Lighthouse)的中间服务器。需要注意的是,流量不一定要经过 Lighthouse 从 A 点到达 B 点。相反,A 点通过查询 Lighthouse 来确定 B 点的位置,然后计算出最快的数据传输方式。设置完成后,我们就可以无限的向外扩展,甚至可以在不同的云提供商上托管基础设施的每个部分。
灯塔(Lighthouse)的配置与监听站(Listeningpost) 完全相同
也为这个主机安装 socat 和 Nebula
sudo apt-get update -y && sudo apt-get install socat
wget https://github.com/slackhq/nebula/releases/download/v1.6.1/nebula-linux-amd64.tar.gz
tar -xvf nebula-linux-amd64.tar.gz
我们为 Lighthouse 制定了一个新的安全组规则,允许入站 UDP 的 4242 端口。这允许我们 Nebula 网络中的主机向 Lighthouse 查询网络中相应的主机。不用担心向所有来源开放此端口是否存在风险,因为连接与查询是需要通过我们接下来要创建的证书进行加密验证的。
# 配置 Nebula
在所有的服务器上安装好需要的组件后,是时候来设置我们的 Nebula 网络了,我们要在本地的团队服务器上设置所有需要用到的证书和配置文件,并且为了安全起见将它们保存在这里。
# 创建 Nebula 证书文件
在本地的团队服务器上的 Nebula 目录下运行以下命令:
mkdir certs && mv nebula-cert certs/
cd certs
./nebula-cert ca -name "ShellCorp, LLC"
./nebula-cert sign -name "lighthouse" -ip "192.168.100.1/24"
./nebula-cert sign -name "listeningpost" -ip "192.168.100.2/24" -groups "listening_posts"
./nebula-cert sign -name "teamserver" -ip "192.168.100.3/24" -groups "teamservers"
ca.key 文件是整个网络设置中最敏感的文件,请妥善保管。
# 创建 Nebula 配置文件
Nebula 网络中的主机需要一个配置文件。配置文件是用 YAML 编写的,非常容易阅读和理解。再次从 Marcello 的帖子中借用并进行修改:
# lighthouse-conf.yml
pki: | |
ca: /home/ubuntu/ca.crt | |
cert: /home/ubuntu/lighthouse.crt | |
key: /home/ubuntu/lighthouse.key | |
static_host_map: | |
"192.168.100.1": ["<LIGHTHOUSE IP>:4242"] | |
lighthouse: | |
am_lighthouse: true | |
listen: | |
host: 0.0.0.0 | |
port: 4242 | |
punchy: | |
punch: true | |
tun: | |
disabled: false | |
dev: nebula1 | |
drop_local_broadcast: false | |
drop_multicast: false | |
tx_queue: 500 | |
mtu: 1300 | |
routes: | |
unsafe_routes: | |
logging: | |
level: info | |
format: text | |
firewall: | |
conntrack: | |
tcp_timeout: 12m | |
udp_timeout: 3m | |
default_timeout: 10m | |
max_connections: 100000 | |
outbound: | |
- port: any | |
proto: any | |
host: any | |
inbound: | |
- port: any | |
proto: icmp | |
host: any | |
- port: 4789 | |
proto: any | |
host: any | |
- port: 22 | |
proto: any | |
cidr: 192.168.100.0/24 |
# listeningpost-conf.yml
pki: | |
ca: /home/ubuntu/ca.crt | |
cert: /home/ubuntu/listeningpost.crt | |
key: /home/ubuntu/listeningpost.key | |
static_host_map: | |
"192.168.100.1": ["<LIGHTHOUSE IP>:4242"] | |
lighthouse: | |
am_lighthouse: false | |
interval: 60 | |
hosts: | |
- "192.168.100.1" | |
listen: | |
host: 0.0.0.0 | |
port: 4242 | |
punchy: | |
punch: true | |
tun: | |
disabled: false | |
dev: nebula1 | |
drop_local_broadcast: false | |
drop_multicast: false | |
tx_queue: 500 | |
mtu: 1300 | |
routes: | |
unsafe_routes: | |
logging: | |
level: info | |
format: text | |
firewall: | |
conntrack: | |
tcp_timeout: 12m | |
udp_timeout: 3m | |
default_timeout: 10m | |
max_connections: 100000 | |
outbound: | |
- port: any | |
proto: any | |
host: any | |
inbound: | |
- port: any | |
proto: icmp | |
host: any | |
- port: 80 | |
proto: any | |
host: any | |
- port: 443 | |
proto: any | |
host: any | |
- port: 4789 | |
proto: any | |
host: any | |
- port: 22 | |
proto: any | |
cidr: 192.168.100.0/24 |
# teamserver-conf.yml
pki: | |
ca: /root/c2/nebula/certs/ca.crt | |
cert: /root/c2/nebula/certs/teamserver.crt | |
key: /root/c2/nebula/certs/teamserver.key | |
static_host_map: | |
"192.168.100.1": ["<LIGHTHOUSE IP>:4242"] | |
lighthouse: | |
am_lighthouse: false | |
interval: 60 | |
hosts: | |
- "192.168.100.1" | |
listen: | |
host: 0.0.0.0 | |
port: 4242 | |
punchy: | |
punch: true | |
tun: | |
disabled: false | |
dev: nebula1 | |
drop_local_broadcast: false | |
drop_multicast: false | |
tx_queue: 500 | |
mtu: 1300 | |
routes: | |
unsafe_routes: | |
logging: | |
level: info | |
format: text | |
firewall: | |
conntrack: | |
tcp_timeout: 12m | |
udp_timeout: 3m | |
default_timeout: 10m | |
max_connections: 100000 | |
outbound: | |
- port: any | |
proto: any | |
host: any | |
inbound: | |
- port: any | |
proto: icmp | |
host: any | |
- port: 80 | |
proto: any | |
host: any | |
- port: 443 | |
proto: any | |
host: any | |
- port: 4789 | |
proto: any | |
host: any | |
- port: 22 | |
proto: any | |
cidr: 192.168.100.0/24 |
根据具体情况修改配置文件中的内容,例如 crt 和密钥文件的位置,确认 Lighthouse 的公共 IP 地址是否填写正确。当 Nebula 网络运行时,Lighthouse 的 IP 地址不应该发生改变。
为了便于故障排除,端口 80 和 443 被设置为允许任何进入 Listeningpost 主机的流量。这本身并不是特别安全,但我们将在 Nebula 配置中将它们保持打开状态,让防火墙来阻止我们不想要的流量。我们将使用安全组设置将其锁定到特定的 IP 地址,以便稍后保留在这里。
我们还可以在防火墙规则中提高安全性并指定主机和协议。也许您希望 SSH 对 Nebula 网络内部的所有内容开放,但也许有一些您不想通信的主机。这个文件是你可以锁定它们的地方。锁定来自 Nebula 网络中其他主机的 Teamserver 上的入口 SSH 可能是一个很好的举措。确实没有任何其他主机需要启动登录到 Teamserver 的 SSH 会话的理由,但我们绝对希望能够从 Teamserver 启动 SSH 会话并访问其他主机。
将以下文件拷贝到各主机:
- 其指定的配置 YAML 文件
- ca.crt
- 其指定文件 [hostname].crt
- 其指定文件 [hostname].key
例如使用 csp,将文件拷贝至服务器 ubuntu 用户的根目录下
scp -i ../../c2.pem lighthouse* ubuntu@lighthouse的IP地址:~/
最终 Lighthouse 服务器上文件:
最终 Listeningpost 服务器上文件:
# 启动 Nebula
Lighthouse 服务器:
sudo ./nebula -config lighthouse-conf.yml
Listeningpost 服务器:
sudo ./nebula -config listeningpost-conf.yml
本地团队服务器:
sudo ./nebula -config certs/teamserver-conf.yml
运行后本地团队服务器会多出一张 nebula1 的网卡
通过 ping 验证一下连通性
# 设置反向端口转发和 SOCAT
接下来是确保流量可以从 listeningpost 的 IP 地址返回到我们本地的团队服务器。
首先在本地的团队服务器创建一个简单页面,测试能否成功通过 listeningpost 的公网地址访问到
mkdir test && cd test
echo "hello world\!" > index.html
python3 -m http.server 80
Listeningpost 的防火墙记得要开放 80 端口
本地服务器上使用 ssh 将流量转到 listeningpost 上
ssh -N -R 8080:localhost:80 -i certs/id_rsa ubuntu@listeningpost
注意这里我为了方便起见,我将其他 Nebula 内的服务器 IP 地址添加到了 hosts 文件,即
192.168.100.1 lighthouse
192.168.100.2 listeningpost
listeningpost 上执行 ss -plont 查看连接状态
sudo socat tcp-listen:80,reuseaddr,fork,bind=Listeningpost的公网IP地址 tcp:127.0.0.1:8080
这里要注意,有些云服务器网卡只有内网地址,配置 socat 时使用公网 IP 地址的话会报错,改用内网地址即可
通过访问 listeningpost 的公网地址,成功访问到本地服务器的测试页面
# 使用测试
这里以 C2 上线进行使用测试,我使用的 C2 选择了 Sliver,关于它的详细使用方法,之后可能会单独进行说明,它的安装十分简单:
curl https://sliver.sh/install | sudo bash
安装完成后输入 sliver 启动。
在团队服务器上,设置 HTTPS 侦听器并将其指向 ssl 证书。
生成 shell。
这里为了演示效果,是直接在受害主机上的 hosts 文件绑定了 listeningpost 的 IP 地址,在受害主机上运行 shell,成功上线。
# 总结
按照上述操作,可成功搭建一个小型的红队基础设施网络。这个小型网络能够在 Nebula 的网状覆盖 VPN 上无限扩展,不仅仅限于 C2 服务端。最重要的是,从红队的角度来看,这个基础设施将是相对安全的,它将最大限度地降低客户数据安全的风险。
# 参考链接
-
https://arstechnica.com/gadgets/2019/12/how-to-set-up-your-own-nebula-mesh-vpn-step-by-step/
-
https://malcomvetter.medium.com/safe-red-team-infrastructure-c5d6a0f13fac
-
https://notes.huskyhacks.dev/blog/red-team-infrastructure-done-right
-
https://gist.github.com/byt3bl33d3r/65819bbb1ea3d1284ccb675409f90dcc
本文仅为学习目的,如有侵权,请联系我删除
本文提及的工具仅供学习使用,禁止用于非法用途,本文不承担任何责任