免责声明:
本文技术只做研究之用,禁止用来从事非法用途,如有使用文章中的技术从事非法活动,一切后果由使用者自负,与作者无关。
一、摘要
在上一篇文章中, 完成了Microsoft Azure 上的环境准备工作, 已经成功安装并配置了用于 Nginx 反向代理的虚拟机(VM)和用于 Cobalt Strike Team 服务器的虚拟机。两台虚拟机都具有内部静态 IPv4 地址,并位于同一虚拟网络中且能正常进行内部通信。在本篇文章中,将完成对Nginx、Cobalt Strike和C2服务的安装、配置和功能测试。
二、Nginx反向代理配置
在Linux VM中如果没有安装Nginx, 使用以下命令安装:
apt install nginx
下一步删除Nginx的默认配置文件,命令如下:
rm /etc/nginx/sites-enabled/default
接着创建一个新的default配置文件用来配置反向代理:
nano /etc/nginx/sites-enabled/default
对于新的默认配置,将使用以下参数,其中 domain.com 必须替换为自己的 C2 域名。在此配置中,定义了使用 Certbot 创建的 SSL 证书的路径。还使用 proxy_pass 参数来定义有效的 HTTPS 请求将被重定向到的 IP 地址。这是 Cobalt Strike Team 服务器的内部 IPv4 地址,由于是 HTTPS 流量,因此使用端口 443。
该配置的一个重要方面是 Nginx 反向代理如何决定传入的 HTTPS 请求是否合法,并且是否应该转发到 Cobalt Strike Team 服务器。这个决定是通过定义 GET 和 POST 请求的 URI 来实现的,这些 URI 稍后将被输入到 Cobalt Strike Malleable 配置文件中。在此示例中,使用 lib-8f74c3d1.min.js 作为 GET 请求的 URI,使用 app.7e5b9f2a.bundle.js 作为 POST 请求的 URI。
简单来说,这意味着当完成 Cobalt Strike Malleable 配置文件的配置后,例如使用配置好的监听器创建一个测试 payload 时,这些定义的 URI 也将被包含在 payload 中。当目标主机植入程序最终尝试通过 CDN -> DNS -> Nginx 路径连接到团队服务器时,Nginx 反向代理将识别这些 URI 为传入 HTTPS 请求的合法部分。这使得代理能够将请求识别为来自Cobalt Strike 植入程序的合法流量,并相应地将 HTTPS 流量转发到团队服务器。
这种方法确保只有经过特别配置的请求才会通过 Nginx 反向代理,从而在外部网络和 Cobalt Strike 团队服务器之间提供了额外的一层安全性和过滤。Nginx配置文件内容如下:
server {listen 443 ssl default_server; # Listen on port 443 for HTTPS as the default server for this IP.listen [::]:443 ssl default_server; # Listen on port 443 for HTTPS on all IPv6 addresses as the default server.ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # Path to the SSL certificate file.ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # Path to the SSL certificate private key file.client_max_body_size 200M; # Set the maximum allowed size of client request body to 200MB.root /var/www/html; # Set the document root to serve files from /var/www/html.server_name _; # Catch-all server block (matches any server name).location ~ ^/(lib-8f74c3d1.min.js|app.7e5b9f2a.bundle.js) {client_max_body_size 200M; # Override the client body size limit to 200MB for these specific files.proxy_pass https://10.3.0.5:443; # Proxy requests for these files to another server at 10.3.0.5 over HTTPS.}
}
下面启动和重启Nginx服务,确保Nginx服务状态正常:
sudo systemctl enable nginx
sudo systemctl restart nginx
sudo systemctl status nginx
三、Cobalt Strike安装配置
对于 Cobalt Strike,需要配置两项内容:在服务器端(Team Server),需要正确配置 Malleable Profile;在客户端,需要正确创建 Cobalt Strike 的监听器。
Malleable Profile - 配置
Malleable Profile 是 Cobalt Strike 的关键组件,它允许自定义和混淆目标植入程序的网络行为,使其看起来像是合法的网络流量,从而更难被检测到。仔细配置 Malleable Profile 对于确保植入程序与 Team Server 之间的通信保持低调并且不会被安全解决方案检测到至关重要。Malleable Profile 定义了网络通信的各个方面,如 HTTP 头、URI、POST 数据及其他植入程序用来与 Team Server 通信的参数。这些定制化操作是为了让 C2 流量看起来像合法的网络流量,从而最大限度地减少其被检测和拦截的可能性。
URIs
GET 和 POST 请求的 URI 必须配置为与 Nginx 配置中定义的 URI 一致。在这个例子中,GET 请求的 URI 为 lib-8f74c3d1.min.js,POST 请求的 URI 为 app.7e5b9f2a.bundle.js。这些 URI 不仅用于通过模拟合法的网络请求来掩盖植入程序流量,还在 Nginx 反向代理的功能中起着核心作用。代理使用这些 URI 来判断请求是否来自植入程序的合法 HTTPS 请求。换句话说,只有当 URI 完全匹配时,HTTPS 流量才会从 Nginx 反向代理转发到 Cobalt Strike Team Server。否则,请求将不会被转发,从而提供额外的安全性,并阻止来自扫描器、机器人、蓝队等的非授权访问。
要配置这一点,需要打开相应的 Malleable Profile,例如 webbug.profile,并在 GET 和 POST 部分添加相应的条目。GET 和 POST 的请求动词(verb)应该已经存在,只需添加 GET 和 POST 的 URI。重要的是,GET 和 POST 的 URI 必须不同,以便 Cobalt Strike 和 Nginx 能够区分这两种 HTTP 方法。在这个示例中,GET 请求使用 URI lib-8f74c3d1.min.js,POST 请求使用 URI app.7e5b9f2a.bundle.js。这些 URI 必须与 Nginx 配置中指定的完全匹配,以确保 Nginx 反向代理能够正确处理流量。如果 URI 匹配,HTTPS 流量将被转发到 Cobalt Strike Team Server,否则请求将被阻止。
Host 头
Host 头也必须正确定义,以确保通过 CDN 的通信能够顺利进行。此头告知 CDN 所要访问的域或子域,并且对于请求的正确转发至 Nginx 反向代理,最终转发到 Cobalt Strike Team Server 至关重要。因此,需要在 Malleable Profile 中为 GET 和 POST 请求添加 Host 参数,并将为 CDN 选择的端点名称作为值。在此例中,该值应为 xyz-cache.azureedge.net。当然,这个头的值必须根据你的 CDN 端点名称进行调整。如下图:
这样就完成了 Mallable 配置文件的配置,显示的配置可确保植入程序生成所需的流量,该流量被 CDN 和 Nginx 反向代理接受并正确转发。
四、Cobalt Strike - Listener监听器配置
最后,需要配置 Cobalt Strike 监听器。创建一个 HTTPS 侦听器。在Hosts字段中,输入要用于隐藏 C2 流量的 CDN 域。这些域是之前为 CDN 配置的端点,在植入程序和 Cobalt Strike Team 服务器之间的通信中发挥着核心作用。如下图:
这样就完成了 Cobalt Strike 和C2 基础设施的配置,其中包括 CDN、DNS、Nginx、Cobalt Strike Team 服务器和客户端。
五、C2安装和测试
要测试 C2 配置的功能, 可以使用curl运行测试,也可以使用Cobalt Strike创建测试负载,并查看Cobalt Strike客户端中是否打开命令和控制连接。
第一步是使用以下curl命令来测试Nginx是否会将请求转发到Cobalt Strike团队服务器。该命令模拟通过 CDN 的 POST 请求。仔细观察该命令,可以看到 CDN 域已正确指定,但 POST URI false_uri.js与在 Nginx 和 Cobalt Strike 的 Malleable 配置文件中定义的 URI 不匹配。命令如下:
curl -X POST https://ajax.microsoft.com/false_uri.js -d test -H "host: xyz-cache.azureedge.net"
由于 URI 与 Malleable 配置文件和 Nginx 配置中定义的 URI 不匹配,Nginx 可能会阻止请求而不将其转发到 Cobalt Strike Team 服务器, 表明安全机制工作正常。如图:
下一步再次使用curl命令,但这次使用Nginx和Malleable配置文件配置中定义的正确URI。同样,我使用的是预构建的配置,因此出于安全原因对正确的 URI 进行了马赛克处理。此测试表明,通过路径 CDN -> DNS C2 域 -> Nginx 反向代理 -> Cobalt Strike Team 服务器成功建立了连接。
与之前使用错误 URI 的测试相比,现在可以看到请求已正确处理并转发到 Cobalt Strike Team 服务器。这证实了C2 基础设施已正确配置并按计划运行。如图:
该测试可确保C2 基础设施的所有组件都能正确通信,并且 Nginx 反向代理能够可靠地将合法请求路由到 Cobalt Strike 团队服务器。作为附加测试,可以在 HTTPS CDN 侦听器的上下文中使用 Cobalt Strike 运行有效负载,以确保从目标植入程序到团队服务器的 C2 通道正确打开。
如下图:
在这种情况下,这里配置了 Nginx 和 Cobalt Strike 侦听器,以便所有通信都通过 HTTPS 进行,这使得使用 Wireshark 等工具分析流量变得困难,因为流量是加密的。但是,如果想使用 Wireshark 更仔细地检查 C2 流量,可以扩展 Nginx 配置以允许端口 80 上的未加密流量。这将涉及在 Cobalt Strike 下设置 HTTP 侦听器并使用 HTTP 而不是 HTTPS 重复测试。这种方法允许详细分析未加密的 C2 流量。
原创 suntiger 二进制空间安全