AWSのIAMポリシーに対するクエリを実行するIAMActionHunterを試してみる
IAMActionHunter
Pacuの開発をしているRhino Security Labsから新たにIAMActionHunterが開発されました。
このIAMActionHunter自体は単体のツールとして提供されていますが、クエリの機能はPacuのモジュールにも追加されています。
IAMActionHunterで実現できること
Rhino Security LabsのブログのOffensive and Defensive Use Cases
を見ると、以下のようにあります。
While other tools perform scans to identify privilege escalation risks, this tool enables a more manual approach, allowing users to investigate any permission they choose and quickly assess the roles, users, and resources they apply to for targeted analysis or privilege escalation path idea generation.
Google翻訳
他のツールは権限昇格のリスクを特定するためにスキャンを実行しますが、このツールはより手動のアプローチを可能にし、ユーザーが選択した権限を調査し、対象を絞った分析や権限昇格パスのアイデア生成のために適用するロール、ユーザー、およびリソースを迅速に評価できるようにします。
今までPacuを積極的に使うようなことがなかったのであまり意識がなかったのですが、iam__bruteforce_permissions
やiam__enum_permissions
のようなモジュールは単一のIAMロールやIAMユーザに焦点を当てたツールでしたが、このツールでは取得したIAMユーザやIAMロールに対して調査したい権限を探す、といった使い方が想定されているようです。
使ってみる
IAMActionHunterの導入
git clone https://github.com/RhinoSecurityLabs/IAMActionHunter.git
cd IAMActionHunter
pip install .
iamactionhunter --help
iamactionhunter --collect --profile <some-aws-profile>
調査用のIAMユーザの作成
今回は調査用にReadOnlyAccess
を持ったIAMユーザを作成しました。
アクセスキーを作成し、認証情報を~/.aws/credentials
に保存します。
私はprofileはiamaction
にしました。
[iamaction]
aws_access_key_id = アクセスキー
aws_secret_access_key = シークレットキー
認証情報の取得
collect
まずはIAMユーザとIAMロールに結び付くポリシーを取得します。
--profile
には~/.aws/credentials
に指定したProfile名を指定すること。
$ iamactionhunter --collect --profile iamaction
Downloading IAM policies for account [AWSアカウントID]...
Finished downloading IAM policies for account [AWSアカウントID].
Processing files for [AWSアカウントID]...
実行すると./actionhunter_output/[AWSアカウントID]
フォルダ配下にjsonファイルが保存される。
list
クエリが実行できるアカウントがリストできるようです。collectを一か所にしかしていないので一つだけ表示されました。
$ iamactionhunter --list
[AWSアカウントID]
query
クエリにs3:putobject*
などアスタリスクを利用できるほか、iam:createrole,sts:assumerole
のようにカンマ区切りに指定することができます。
出力パターンとしては[+]
がそのアクションを許可できるユーザ/ロールで、[-]
にコンディション句などで権限が制限していることを表しているようです。
サンプル
[+] role:aws-elasticbeanstalk-service-role vulnerable to CreateEC2WithExistingIP:
ec2:runinstances
*
[-] With the following conditions:
{'ArnLike': {'ec2:LaunchTemplate': 'arn:aws:ec2:*:*:launch-template/*'}}
iam:passrole
arn:aws:iam::*:role/*
[-] With the following conditions:
{'StringEquals': {'iam:PassedToService': ['elasticbeanstalk.amazonaws.com', 'ec2.amazonaws.com', 'ec2.amazonaws.com.cn', 'autoscaling.amazonaws.com', 'elasticloadbalancing.amazonaws.com', 'ecs.amazonaws.com', 'cloudformation.amazonaws.com']}}
恐らく以下のフォーマット
[-]
は該当すれば表示
[+] principal:iam名/role名 vulnerable to 該当するポリシー名:
アクション1(iam:passroleなど)
アクション1のリソース
[-] With the following conditions:
{コンディション句}
アクション2(iam:passroleなど)
アクション2のリソース
etc...
以下は私の環境での実行結果のAWS CDKに関連するロールでの抜粋です。基本は検証で使う程度で常駐しているリソースはないものの放置されてるIAMロールなどがいくつかあるはずです。
今回は全部で167件の出力。
$ iamactionhunter --account [AWSアカウントID] --query s3:putobject*
< --snip-- >
[+] role:cdk-hnb659fds-cfn-exec-role-[AWSアカウントID]-ap-northeast-1 can perform s3:putobjectlegalhold on the following resources:
*
< --snip-- >
[+] role:cdk-hnb659fds-file-publishing-role-[AWSアカウントID]-ap-northeast-1 can perform s3:putobjecttagging on the following resources:
arn:aws:s3:::cdk-hnb659fds-assets-[AWSアカウントID]-ap-northeast-1
arn:aws:s3:::cdk-hnb659fds-assets-[AWSアカウントID]-ap-northeast-1/*
< --snip-- >
[+] role:cdk-hnb659fds-deploy-role-[AWSアカウントID]-us-west-2 can perform s3:putobjecttagging on the following resources:
*
[-] With the following conditions:
{'StringNotEquals': {'s3:ResourceAccount': '[AWSアカウントID]'}}
< --snip-- >
別パターンの表示
恐らくいろいろなパターンがあると思いますが、たまたま見つけたので一応載せておきます。
[+] role:AWSServiceRoleForEC2Spot can perform ec2:runinstances on the following resources:
*
[-] If the resources are not included in:
arn:aws:ec2:*:*:instance/*
[-] These Deny rules only apply if the following conditions are met:
{'StringNotEquals': {'ec2:InstanceMarketType': 'spot'}}
user/role
--user
,--role
で結果のフィルタ。
cdk-hnb659fds-deploy-role-
やcdk-hnb659fds-deploy-role-*
での部分一致はできませんでした。
$ iamactionhunter --account [AWSアカウントID] --query s3:putobject* --role cdk-hnb659fds-deploy-role-[AWSアカウントID]-us-west-2
[+] role:cdk-hnb659fds-deploy-role-[AWSアカウントID]-us-west-2 can perform s3:putobjectversiontagging on the following resources:
*
[-] With the following conditions:
< --snip-- >
csv
結果をcsvファイルとして出力。
Principal,Allowed Action,Denied Action,Resource,Conditions
user:pacu-iam,ses:getimportjob,,*,[]
user:pacu-iam,rds:describedbparametergroups,,*,[]
< --snip-- >
role:cdk-hnb659fds-deploy-role-[AWSアカウントID]-ap-northeast-1,s3:deleteobject,,*,[{'StringNotEquals': {'s3:ResourceAccount': '[AWSアカウントID]'}}]
< --snip-- >
config
configs/
配下に置くことで、--config
で指定した条件でクエリできるっぽい。
、、、が、jsonファイルを適当に書いてみたが動かせなかった。
読み込めてはいそうなので設定ファイルが違うのかもしれない。all.pyに追記すれば動きそうな気はするが試していない。
{
"Description": "",
"Name": "DangerousIAMActions",
"ActionsNeeded": [
"s3:putobject*"
],
"AllOrNone": "0"
}
$ iamactionhunter --account [AWSアカウントID] --config mys3
Traceback (most recent call last):
File "/home/lea/.local/bin/iamactionhunter", line 8, in <module>
sys.exit(main())
File "/home/lea/.local/lib/python3.10/site-packages/IAMActionHunter/IAMActionHunter.py", line 312, in main
process_config_file_query(permissions, config, f"{principal_type}:{principal_name}", args)
File "/home/lea/.local/lib/python3.10/site-packages/IAMActionHunter/IAMActionHunter.py", line 171, in process_config_file_query
query = config["ActionsNeeded"]
TypeError: string indices must be integers
ブログにあるdangerous_iamはデフォルトで入っている。
他にはwrite系アクションを見つけるためのwrite_actions
と権限昇格につながるアクションを見つけるprivescs
がありました。
$ iamactionhunter --account [AWSアカウントID] --config dangerous_iam
[+] role:pacu-role vulnerable to DangerousIAMActions:
iam:putrolepolicy
*
iam:createloginprofile
*
< --snip-- >
$ iamactionhunter --account [AWSアカウントID] --config privescs
< --snip-- >
[+] role:aws-elasticbeanstalk-service-role vulnerable to CreateEC2WithExistingIP:
ec2:runinstances
*
[-] With the following conditions:
{'ArnLike': {'ec2:LaunchTemplate': 'arn:aws:ec2:*:*:launch-template/*'}}
iam:passrole
arn:aws:iam::*:role/*
[-] With the following conditions:
{'StringEquals': {'iam:PassedToService': ['elasticbeanstalk.amazonaws.com', 'ec2.amazonaws.com', 'ec2.amazonaws.com.cn', 'autoscaling.amazonaws.com', 'elasticloadbalancing.amazonaws.com', 'ecs.amazonaws.com', 'cloudformation.amazonaws.com']}}
< --snip-- >
all or none
--all-or-none
を付けることで、queryのすべてにマッチするものだけを出力することができます。
iam:createrole
とsts:assumerole
について-all-or-none
の出力を比較します。
$ iamactionhunter --account [AWSアカウントID] --query iam:createrole,sts:assumerole --all-or-none | wc -l
54
$ iamactionhunter --account [AWSアカウントID] --query iam:createrole,sts:assumerole | wc -l
65
私の環境では以下の3つのroleが差分として出力されています。
[+] role:AWSServiceRoleForCloudFormationStackSetsOrgMember can perform iam:createrole on the following resources:
arn:aws:iam::*:role/stacksets-exec-*
[+] role:AWSReservedSSO_AWSPowerUserAccess_895d5e4887af7b9f can perform sts:assumerole on the following resources:
*
[+] role:AWSServiceRoleForSSO can perform iam:createrole on the following resources:
arn:aws:iam::*:role/aws-reserved/sso.amazonaws.com/*
[-] With the following conditions:
{'StringNotEquals': {'aws:PrincipalOrgMasterAccountId': '${aws:PrincipalAccount}'}}
AWSServiceRoleForCloudFormationStackSetsOrgMember
にはAWSマネージド管理ポリシーであるCloudFormationStackSetsOrgMemberServiceRolePolicy
のみがアタッチされています。
ポリシーの通り、iam:createrole
の権限を持つが、sts:assumerole
は持っていないようです。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iam:CreateRole",
"iam:DeleteRole",
"iam:GetRole"
],
"Effect": "Allow",
"Resource": [
"arn:aws:iam::*:role/stacksets-exec-*"
]
},
{
"Action": [
"iam:DetachRolePolicy",
"iam:AttachRolePolicy"
],
"Effect": "Allow",
"Resource": [
"arn:aws:iam::*:role/stacksets-exec-*"
],
"Condition": {
"StringEquals": {
"iam:PolicyARN": "arn:aws:iam::aws:policy/AdministratorAccess"
}
}
}
]
}
おわりに
クエリをたたく用途が見つけられる人にはいい感じに使えそうな気がするが、そもそも何をクエリにすればいいかを見つけるのはなかなかレベルが要求されそう。
他人任せだけども、、dangerous_iam
のようなデフォルトで使えるconfigがあるととりあえず使ってみようとはなりそうなので、いい感じに増えてほしい。。
同様の機能がpacuにあると書いてあるが、configの機能はなかったように思うのであくまでクエリができるところまでっぽい。ちゃんと確認はしてない。
csvのアウトプットなど、Excelで操作できるとかは用途がある気はするので、単体のツールとしてある理由も理解できるので、入れておいてもいいかも。
リソースポリシーも見れると嬉しいけどさすがに範囲が広くて難しそうかな。。
Discussion