云服务器SSRF漏洞利用IMDS窃取IAM凭证的攻防实战 📅 2026/7/1 10:31:58 1. 项目概述当云服务器“内鬼”泄露了你的钥匙在云上构建应用我们常常把云服务器实例比如AWS的EC2当作一个可信的、与世隔绝的“黑盒”。我们通过安全组、IAM角色、密钥对来保护它却很容易忽略一个事实这个“黑盒”内部运行着我们自己的、可能存在缺陷的应用程序。EC2元数据服务IMDS攻击特别是通过服务器端请求伪造SSRF漏洞进行的凭证窃取就是攻击者利用我们自己的应用程序作为跳板从内部“合法”地偷走云环境访问权限的经典手法。这就像你把家门钥匙藏在了玄关的鞋柜里自以为安全却没想到小偷通过你家客厅窗户的缝隙伸手进来就能轻松拿到钥匙。简单来说这个攻击链条的核心是一个有漏洞的Web应用SSRF → 访问实例内部的元数据服务IMDS → 获取临时安全凭证如IAM角色令牌 → 接管云上资源。我见过太多案例开发者精心设计了复杂的VPC网络隔离和精细的IAM策略却因为一个简单的、未经验证的用户输入导致的SSRF漏洞让整个防御体系形同虚设。攻击者甚至不需要知道你的账号密码他们利用的是云平台为实例管理而设计的、默认存在的“后门”服务。对于云安全工程师、渗透测试人员和后端开发者而言理解这种攻击的原理、手法和防御措施是构建真正纵深防御的必修课。这不仅仅是修补一个漏洞更是从根本上扭转“内部即可信”的危险思维定式。接下来我将拆解这个攻击的每一个环节从元数据服务是什么、SSRF如何利用它到如何一步步窃取凭证并扩大战果最后分享从防御者视角该如何层层设防。2. 核心组件拆解元数据服务与SSRF漏洞的致命结合要理解整个攻击我们必须先弄明白两个关键组件EC2元数据服务IMDS和服务器端请求伪造SSRF漏洞。它们单独来看可能危害有限但一旦结合就产生了奇妙的“化学反应”。2.1 EC2元数据服务实例的“身份证”与“临时通行证”AWS EC2元数据服务是一个运行在实例内部特殊链路本地地址169.254.169.254上的HTTP服务。这个地址在公共互联网上是不可路由的只有从EC2实例内部发起的请求才能访问到它。它的设计初衷是为了让运行在实例上的应用程序能够方便地获取关于自身的信息而无需硬编码或进行复杂的外部配置。你可以把它想象成实例的“内置信息查询台”。通过向这个地址发送HTTP请求应用可以获取到两大类关键信息实例元数据包括实例ID、实例类型、所属可用区、AMI ID、网络配置MAC地址、子网ID、VPC ID、安全组等。这些信息对于应用程序进行自我配置和发现很有用。实例动态数据这部分是安全问题的核心主要指IAM角色临时安全凭证。当为一个EC2实例附加一个IAM角色后元数据服务就会提供获取该角色临时凭证的接口。获取凭证的典型路径是http://169.254.169.254/latest/meta-data/iam/security-credentials/role-name。访问这个端点你会得到一个JSON响应包含AccessKeyId、SecretAccessKey、Token和过期时间。任何能访问这个端点的进程就等于拿到了该IAM角色所代表权限的“临时门禁卡”。注意这里存在版本差异。AWS推出了IMDSv2这是一种基于会话的、要求请求头令牌的增强版本旨在缓解一些简单的SSRF攻击。但许多实例仍在使用或不完全兼容IMDSv1且攻击手法也在进化以应对v2。我们后续会详细讨论IMDSv2及其绕过。2.2 SSRF漏洞让服务器成为你的“代理”服务器端请求伪造SSRF是一种安全漏洞攻击者能够诱使服务器端应用程序向攻击者指定的任意地址发起HTTP请求。漏洞通常源于应用程序未对用户提供的URL参数进行充分验证和过滤。例如一个常见的脆弱功能是“网页截图”或“URL预览”服务# 伪代码示例 import requests def fetch_url_preview(user_provided_url): # 危险未验证用户输入的URL response requests.get(user_provided_url) return process_preview(response.content)攻击者可以提交http://169.254.169.254/latest/meta-data/iam/security-credentials/作为user_provided_url。服务器端的应用程序会忠实地向这个内部地址发起请求并将元数据服务的响应内容即IAM凭证返回给攻击者或者在某些场景下触发其他内部网络动作。SSRF的成因多样除了直接URL获取还可能通过文件上传功能某些服务会解析上传文件中的URL如XML文件中的外部实体。数据库连接某些应用允许通过URL连接外部数据库。内部API调用应用根据用户输入拼接内部API地址。关键在于攻击者利用了服务器在网络位置上的特权即能够访问169.254.169.254将服务器变成了一个跳板或代理。2.3 结合点从漏洞到权限提升当存在SSRF漏洞的应用程序运行在EC2实例上时攻击面就产生了质变。普通的SSRF可能只能扫描内网端口或攻击内部脆弱服务危害局限于内部网络。但结合EC2 IMDSSSRF直接升级为云环境权限提升漏洞。攻击路径变得极其清晰发现入口攻击者通过黑盒测试、代码审计或意外发现找到一个SSRF漏洞点。指向元数据构造指向169.254.169.254的恶意请求。枚举与窃取首先访问/latest/meta-data/iam/security-credentials/来列出可用的IAM角色名如果实例附加了角色。然后访问具体角色路径获取完整的临时凭证JSON。权限兑现使用窃取的AccessKeyId,SecretAccessKey, 和Token通过AWS CLI、SDK或任何兼容工具以该IAM角色的权限执行操作。攻击者现在“扮演”了这台EC2实例。此时攻击者拥有的权限完全取决于该IAM角色的策略。如果角色权限宽松例如AdministratorAccess或包含了s3:*、ec2:*等高风险操作攻击者就可以窃取S3桶数据、创建新的EC2实例、修改网络配置、甚至尝试横向移动到其他账号资源。3. 攻击链实战模拟从发现到横向移动纸上谈兵终觉浅我们通过一个模拟的实战场景来还原攻击者可能采取的完整步骤。假设我们有一个脆弱的Web应用运行在EC2上并且该实例被附加了一个具有S3读取权限的IAM角色。3.1 第一阶段漏洞探测与验证攻击者首先需要确认SSRF漏洞的存在。常见探测手法包括基本回显测试尝试让服务器请求一个攻击者控制的服务器如Burp Collaborator、RequestBin观察是否有HTTP请求到达。http://vulnerable-app.com/fetch?urlhttp://your-collaborator-domain.com协议探测尝试使用file://,gopher://,dict://等协议看服务器是否支持并执行。端口扫描利用SSRF对服务器本地端口进行扫描例如http://127.0.0.1:22、http://127.0.0.1:3306通过响应时间或错误信息判断端口开放情况。一旦确认存在SSRF且服务器会返回请求内容攻击者下一步就是尝试访问元数据端点。实操要点在测试时一个关键的技巧是使用差分响应。先请求一个已知存在的公网URL如https://httpbin.org/get获取正常响应格式和大小。再请求http://169.254.169.254/latest/meta-data/。如果响应截然不同例如返回了instance-id等关键字即可基本断定实例元数据服务可访问。如果应用不直接回显响应体可以尝试通过错误信息、响应时间访问不存在的内部地址可能超时更快或Out-of-Band (OOB)技术如DNS解析来间接验证。3.2 第二阶段元数据信息收集与凭证窃取验证了通往IMDS的道路后攻击者开始系统性地收集信息。获取基础元数据访问http://169.254.169.254/latest/meta-data/。这会返回一个目录列表。关键的子路径包括iam/security-credentials/-核心目标列出附加的IAM角色。instance-id- 实例标识。local-ipv4/public-ipv4- 网络信息。mac- 网络接口MAC地址可用于获取更细粒度的元数据。枚举IAM角色访问http://169.254.169.254/latest/meta-data/iam/security-credentials/。如果实例附加了角色响应会是一个角色名称例如s3-readonly-role。如果没有附加角色通常会返回404或空内容。窃取临时凭证访问http://169.254.169.254/latest/meta-data/iam/security-credentials/s3-readonly-role。响应是一个JSON对象{ Code: Success, LastUpdated: 2023-10-27T12:00:00Z, Type: AWS-HMAC, AccessKeyId: ASIAXXXXXXXXXXXXXXXX, SecretAccessKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, Token: 非常长的会话令牌字符串..., Expiration: 2023-10-27T18:00:00Z }AccessKeyId、SecretAccessKey和Token是接下来攻击的“三件套”。重要心得临时凭证通常有效期为1到6小时。这意味着攻击者有一个时间窗口进行操作。他们可能会编写脚本定期窃取凭证以维持访问或者立即使用凭证进行高价值操作。此外这些凭证是特定区域Region的攻击者需要在使用时指定正确的区域。3.3 第三阶段权限利用与横向移动拿到凭证后攻击者会迅速将其投入使用。首先配置本地环境export AWS_ACCESS_KEY_IDASIAXXXXXXXXXXXXXXXX export AWS_SECRET_ACCESS_KEYxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx export AWS_SESSION_TOKEN非常长的会话令牌字符串...或者使用aws configure设置一个新的profile。接下来攻击者会评估该角色的权限并尝试扩大战果权限枚举使用窃取的凭证调用IAM的GetCallerIdentity和SimulatePrincipalPolicy如果权限允许来了解角色身份和具体权限。更直接的方式是进行“试探性”API调用。数据窃取如果角色有S3权限立即列出和下载敏感桶内数据。aws s3 ls aws s3 sync s3://sensitive-bucket ./local-dump/资源探查与创建检查EC2、RDS、Lambda等其他服务寻找敏感数据或尝试创建后门资源如新的具有公网IP的EC2实例用于建立持久化通道。横向移动跨账户如果当前角色具有sts:AssumeRole权限可以尝试代入其他更高级别的角色。同账户内利用现有权限如ec2:DescribeInstances,ssm:SendCommand探查同一VPC内其他实例如果其他实例也附加了高权限角色可能构成跳板链。持久化在云环境中留下后门例如创建新的IAM用户、添加额外的密钥对、在Lambda函数中植入代码、修改现有实例的用户数据User Data等。一个真实的踩坑案例在一次内部演练中我们利用一个SSRF拿到了一个仅有s3:GetObject权限的角色凭证。起初觉得危害有限。但进一步枚举发现该S3桶里存放着其他服务器的SSH私钥和加密的配置文件。通过解密配置我们获得了数据库凭证和另一个更高权限的IAM角色的ARN。通过S3桶策略中的漏洞我们间接获得了代入那个角色的能力最终升级到了管理员权限。这说明云上的资产关联性极强一个低权限的突破口往往能通过复杂的依赖链导致严重的后果。4. 对抗升级IMDSv2与攻击者的绕过尝试面对IMDSv1的简单性带来的风险AWS推出了IMDSv2Instance Metadata Service Version 2。IMDSv2采用了一种基于会话和令牌的模型显著提高了利用门槛。4.1 IMDSv2的核心安全机制IMDSv2要求所有请求除了创建会话的初始请求都必须包含一个特殊的令牌X-aws-ec2-metadata-token这个令牌需要通过一个PUT请求到特定端点来获取并且该PUT请求必须包含一个自定义的TTL生存时间头。基本流程如下客户端向http://169.254.169.254/latest/api/token发起一个PUT请求并携带头X-aws-ec2-metadata-token-ttl-seconds: 21600例如6小时。IMDSv2服务返回一个令牌一个长字符串。客户端在后续获取元数据的GET请求中携带头X-aws-ec2-metadata-token: 上一步获取的令牌。令牌过期后需要重新执行步骤1。这个机制极大地限制了简单的SSRF攻击因为请求方法限制大多数SSRF漏洞场景是GET请求而获取令牌需要PUT方法。头部依赖需要构造包含特定头部的HTTP请求。状态性需要先完成一个请求用其响应作为下一个请求的头部这在许多盲SSRFBlind SSRF场景下难以实现。4.2 攻击者的绕过与利用技术然而安全总是道高一尺魔高一丈。攻击者和研究人员已经发现了在特定条件下绕过或利用IMDSv2的方法服务器端请求链SSRC或内部服务代理如果存在SSRF的应用本身支持PUT方法或者存在另一个内部服务可以代理任意HTTP请求包括PUT那么攻击者就可以通过两次请求来完成攻击第一次触发PUT获取令牌第二次用GET携带令牌获取凭证。这要求SSRF漏洞点功能更强大或存在多个关联漏洞。利用IMDSv1的向后兼容性AWS允许在启动实例时选择IMDS版本。默认配置可能同时启用IMDSv1和v2或者某些旧实例、自定义AMI镜像仍只使用IMDSv1。攻击者会首先尝试v1端点如果失败再尝试v2。使用工具如aws_metadata_ssrf或cloud-metadata可以自动进行这种探测。通过其他漏洞获取令牌如果攻击者已经通过其他方式如文件包含、目录遍历、日志读取能够读取服务器文件系统他们可能会尝试查找存储或缓存了令牌的临时文件。虽然IMDSv2令牌设计为仅存于内存但某些应用程序或库的不当处理可能留下痕迹。利用应用程序框架的HTTP客户端特性一些HTTP客户端库在收到重定向3xx响应时可能会自动跟随并携带原始请求的头部。如果攻击者能控制一个服务器使其对PUT /latest/api/token的请求返回一个重定向到GET /latest/meta-data/...并且重定向响应中包含了令牌那么某些客户端可能会在跟随重定向时将令牌头传递给元数据服务。这种场景非常特定且罕见。防御视角最根本的防御是强制使用IMDSv2并禁用IMDSv1。在启动实例时可以在“高级详情”中设置元数据服务版本为“仅V2”。对于已有实例可以使用AWS CLI修改aws ec2 modify-instance-metadata-options \ --instance-id i-1234567890abcdef0 \ --http-tokens required \ --http-endpoint enabled--http-tokens required表示强制使用IMDSv2需要令牌optional则表示允许v1和v2。5. 防御体系构建从代码到架构的多层防护单一的防御措施很容易被绕过对抗SSRFIMDS攻击需要一套从开发到运维的纵深防御体系。5.1 应用层防御堵住漏洞源头这是最根本的一层防止SSRF漏洞的产生。输入验证与白名单绝对禁止直接使用用户输入拼接URL并发起请求。建立白名单如果业务必须请求外部URL应基于域名或IP建立严格的白名单机制。使用正则表达式或专门的库进行验证。解析与重构使用urlparsePython、URIJava、new URL()JavaScript等库解析用户输入提取主机名、协议、端口并与白名单比对。只允许HTTP和HTTPS协议禁止file、gopher、dict、sftp等危险协议。import urllib.parse ALLOWED_DOMAINS [trusted.com, cdn.trusted.com] def safe_fetch_url(user_input): parsed urllib.parse.urlparse(user_input) if parsed.scheme not in (http, https): raise ValueError(Unsupported protocol) if parsed.hostname not in ALLOWED_DOMAINS: raise ValueError(Domain not allowed) # 才进行请求 response requests.get(user_input, timeout5) return response使用网络层过滤库对于无法建立白名单的复杂场景使用如libcurlCURLOPT_RESOLVE、requests配合自定义Adapter或专门的SSRF防护库这些库可以在发起请求前进行DNS解析和IP地址过滤阻止对内部IP如127.0.0.1、169.254.169.254、10.0.0.0/8等的请求。设计安全的默认行为避免应用在启动或出错时自动从元数据服务获取配置。如果需要应使用明确的、受控的配置源如AWS Systems Manager Parameter Store, Secrets Manager并通过IAM角色权限严格控制访问。5.2 基础设施层防御缩小攻击面即使应用有漏洞也可以通过基础设施配置来限制危害。强制使用并正确配置IMDSv2如前所述为新实例和现有实例配置http-tokensrequired。考虑设置http-put-response-hop-limit1防止令牌在代理链中被传递。遵循最小权限原则配置IAM角色为EC2实例附加的IAM角色权限必须最小化。一个只负责从S3读日志的应用绝不需要EC2FullAccess。使用条件键Condition Keys进一步限制权限。例如可以为S3权限添加条件限制只能访问特定的桶前缀。{ Effect: Allow, Action: s3:GetObject, Resource: arn:aws:s3:::my-app-logs-bucket/*, Condition: { StringEquals: { s3:prefix: app-a/ } } }定期审计和轮换IAM角色凭证。虽然临时凭证会自动过期但角色策略本身需要定期审查。使用代理或防火墙规则在实例级别使用主机防火墙如iptables、ufw阻止除了特定应用进程外对169.254.169.254:80的访问。但这需要精细的管理可能影响需要合法访问元数据的系统服务。在网络层面某些安全组或NACL配置可以尝试限制但元数据流量是链路本地通常不经过这些网络控制层。使用VPC端点与私有子网将实例部署在私有子网减少直接暴露在互联网的风险从而降低被攻击者发现和利用SSRF漏洞的概率。对于需要访问的AWS服务如S3、DynamoDB使用VPC端点Gateway Endpoint 或 Interface Endpoint避免流量经过公网。5.3 监控与响应层及早发现快速处置没有100%的防御因此必须建立有效的监控来检测异常行为。监控CloudTrail日志启用CloudTrail并记录所有区域的所有管理事件和数据事件特别是S3、Lambda等。设置告警关注来自EC2实例元数据服务关联的IAM角色的异常API调用。例如一个平时只调用s3:GetObject的角色突然调用了ec2:RunInstances或iam:CreateUser。API调用来源IP地址异常如果角色凭证在实例外部被使用。可以使用AWS GuardDuty它内置了检测“EC2实例凭证被用于从该实例外部发起API调用”的威胁情报。监控实例元数据访问日志虽然IMDS本身不提供访问日志但可以通过在实例上部署主机级入侵检测系统HIDS如Osquery、Wazuh或商业EDR来监控对169.254.169.254的网络连接或相关进程活动。监控应用程序日志寻找异常的URL请求参数特别是包含169.254、metadata等关键词的请求。建立事件响应流程一旦检测到凭证泄露立即在IAM中撤销该角色的当前会话。可以分离DetachIAM角色或者更精细地修改角色信任策略或添加拒绝特定访问的权限边界。排查受影响的EC2实例找出并修复SSRF漏洞根源。审查在凭证泄露期间发生的所有API活动评估影响范围进行必要的恢复操作。6. 高级利用场景与防御思考除了直接窃取附加实例的IAM角色凭证攻击者还可能利用元数据服务进行更隐蔽或间接的攻击。6.1 用户数据脚本利用EC2实例的“用户数据”User Data是在启动时传递给实例的脚本或配置文本通常用于自动化初始化。用户数据可以通过元数据服务访问http://169.254.169.254/latest/user-data。如果用户数据脚本中硬编码了敏感信息如数据库密码、API密钥攻击者通过SSRF读取后可能获得进一步渗透的跳板。更危险的是如果实例配置允许用户数据可以被修改通常需要停止-修改属性-启动实例权限要求较高。攻击者可能注入恶意脚本在实例下次启动时执行。防御绝对不要在用户数据中存储明文密码或长期有效的密钥。使用Secrets Manager或Parameter Store并在启动脚本中通过元数据服务获取临时凭证来访问这些秘密。对ec2:ModifyInstanceAttribute权限进行严格控制。6.2 容器环境中的风险在ECSEC2启动模式或EKS中容器运行在EC2实例上。如果容器内的应用存在SSRF漏洞它同样可以访问宿主机的元数据服务169.254.169.254从而窃取EC2实例角色的凭证。这个角色权限往往很大因为它需要管理容器集群。防御使用ECS的任务IAM角色Task IAM Role或EKS的IAM角色服务账户IRSA为每个任务或Pod分配独立的、最小权限的IAM角色避免使用宽泛的实例角色。在容器运行时层面进行网络隔离使用--networknone或用户自定义网络但需仔细评估对业务的影响。在Kubernetes中可以通过安全上下文Security Context或Pod Security PoliciesPSP/ Pod Security StandardsPSS限制容器的能力例如禁用CAP_NET_RAW能力可以防止容器内发送原始网络包可能干扰某些SSRF利用但非根本解决方案。6.3 混合代理与协议混淆攻击在复杂的网络架构中如果存在内部代理服务器且该代理服务器配置不当如未过滤内部地址攻击者可能通过SSRF让应用请求http://internal-proxy:8080并以该代理为跳板访问到原本无法直接到达的元数据服务。或者利用某些协议解析器的特性如URL解析差异、DNS重绑定等来绕过简单的字符串过滤。防御确保所有内部代理、负载均衡器都配置了严格的目标地址过滤策略。在应用代码中不仅要验证用户输入的“域名”更要解析出最终的“IP地址”进行判断。使用可靠的网络库并关注其安全更新。7. 工具与自动化检测对于防御者自动化检测工具至关重要。静态应用安全测试SAST在代码中扫描可能导致SSRF的漏洞模式如未经验证的requests.get()、HttpClient调用等。集成到CI/CD流程中。动态应用安全测试DAST与渗透测试定期对Web应用进行黑盒扫描和人工渗透测试主动尝试SSRF payload探测元数据端点。工具如Burp Suite的Collaborator功能、ffuf、Gopherus等非常有效。云安全态势管理CSPM使用AWS Security Hub、Prisma Cloud、Wiz等CSPM工具持续扫描云环境配置识别“EC2实例启用了IMDSv1”或“EC2实例附加了过高权限IAM角色”等风险项。自定义监控脚本编写脚本定期检查CloudTrail日志寻找来自已知实例角色但行为模式异常如地理位置上不可能、操作类型突变的API调用。我个人在构建云安全体系时会强制将“IMDSv2 Only”和“IAM角色权限最小化”作为安全基线的一部分并通过自动化工具在资源创建时如CloudFormation、Terraform的校验钩子和运行中持续检查。同时对开发团队进行持续的安全培训将“禁止直接请求用户提供的URL”作为一条铁律比任何技术防护都更有效。云安全是共同责任模型开发者的安全编码意识是保护那扇“玄关窗户”的第一道也是最重要的一道锁。