在本文中,我将与您分享我在使用SSM代理通信进行后开发方面所做的一些研究。请注意,我在这里不是指SSM代理或SSM中的安全漏洞。鉴于SSM处理身份验证的方式,如果我们可以访问EC2实例的IAM凭证,这意味着我们可以拦截EC2消息以及SSM会话。这甚至允许低特权用户拦截这些通信。接下来,我们将解释攻击者如何拦截和修改这些通信并完全阻止资源所有者访问EC2实例。此外,这些内容还可以帮助您更好地理解SSM代理在底层是如何运行的。概念验证PoC脚本可以通过单击[此处]获得。拦截EC2消息如果您曾经拦截过SSM代理流量,您会注意到它一直在调用ec2messages:GetMessages。默认情况下,代理将继续执行此操作,使连接保持打开状态约20秒。在这20秒的时间间隔内,代理将继续侦听消息。如果收到一条消息,比如说一个组件调用ssm:SendCommand,它将通过这个打开的连接接收消息。我们也可以自己调用ec2messages:GetMessages,这将允许我们拦截传入到实例的EC2消息。但是有一个小问题,SSM代理将大约每20秒建立一次此连接。如果同时有两个竞争连接怎么办?AWS只会响应最近建立的连接。因此,如果SSM代理首先运行,我们可以在其上创建一个新连接并拦截消息。我们可以通过反复打开新的连接来确保我们有最新的连接,这样我们就可以保证我们的连接始终是最新的,实现对EC2消息的拦截。为了测试我的想法,我创建了一个简单的PoC,用于侦听发送命令消息并窃取命令内容。这种方法的另一个优点是我们可以回复我们想要的任何回复。例如,我们可以提供“成功”并返回一条有趣的消息。下面给出一个PoC示例:拦截SSMsessionEC2消息的实现比较简单,可以查看是否收到消息,并进行相应的操作或响应。不幸的是,SSM会话相对复杂,涉及多个Web套接字连接、一个独特的二进制协议等等。SSM代理启动后不久,它会创建一个返回AWS的WebSocket连接。这个连接会作为一个控制通道,主要负责监听连接请求。当用户尝试启动SSM会话(ssm:StartSession)时,控制通道将接收请求并生成数据通道。这个数据通道主要负责传输用户和EC2实例之间的实际通信消息。它是一种专用的二进制协议,用于处理两端之间的消息传输。幸运的是,我们可以获得SSM代理的[源代码],所以我们要做的就是检查它的源代码和定义的规范。从攻击者的角度来看,拦截SSM会话比拦截EC2消息更可靠。这是因为控制通道的寿命更长,并且与EC2消息一样,AWS仅与最新的通道通信。这样,我们就可以创建自己的控制通道并监听传入的会话。通过使用SSM代理的源代码,我们能够以二进制格式制作消息(如果您查看我提供的PoC代码,您会发现我刚刚翻译了GoToPython),并与会话进行交互。所以现在,我们可以做的如下图所示:或者,我们也可以做一些其他的事情,比如窃取命令并提供我们自己的输出,或者试图拦截和读取发送到设备的用户凭证等。
