关于PMapper
PMapper是一款功能强大的脚本工具,该工具本质上是一个基于Python开发的脚本/代码库,可以帮助广大研究人员识别一个AWS账号或AWS组织中存在安全风险的IAM配置,并对IAM权限执行快速评估。
PMapper可以将目标AWS帐户中的不同IAM用户和角色建模为有向图,从而帮助广大研究人员检查权限提升以及攻击者访问AWS资源或操作所可能采取的替代路径。PMapper还提供了一种查询机制,该机制使用了AWS授权行为的本地模拟方法,当运行查询以确定主体是否有权访问某个操作/资源时,PMapper还会检查该用户或角色是否可以访问其他有权访问该操作/资源的用户或角色。
工具要求
PMapper基于Python 3.5+开发,并使用了botocore库构建项目功能。除此之外,PMapper还需要pydot和graphviz这两个依赖组件,其中pydot可以通过pip安装,graphviz可以访问下列地址获取Windows、macOS和Linux版本:
Graphviz
工具安装
由于该工具基于Python 3.5开发,因此我们首先需要在本地设备上安装并配置好Python 3.5+环境。接下来,广大研究人员可以使用下列方法完成工具的下载和安装。
Pip安装
pip install principalmapper
源码安装
首先,使用下列命令将该项目源码克隆至本地:
git clone git@github.com:nccgroup/PMapper.git
然后使用pip完成工具的安装:
cd PMapper pip install .
Docker使用
将项目源码克隆至本地之后,切换到项目目录中,并执行下列命令:
cd PMapper docker build -t $TAG . docker run -it $TAG
我们可以在调用docker run ...命令时,使用-e|--env或--env-file传递AWS_*环境变量,或使用-v加载你的~/.aws/目录,并使用AWS_CONFIG_FILE和AWS_SHARED_CREDENTIALS_FILE环境变量。
工具使用
为目标账号创建一个有向图,并通过AWS CLI配置访问:
$ pmapper --profile skywalker graph create # [... graph-creation output goes here ...]
运行一个查询,并查看谁创建了IAM用户:
$ pmapper --profile skywalker query 'who can do iam:CreateUser' # [... query output goes here ...]
运行一个查询,并查看谁启动了一个消耗大量资源的EC2实例(排除admin用户):
$ pmapper --account 000000000000 argquery -s --action 'ec2:RunInstances' --condition 'ec2:InstanceType=c6gd.16xlarge' # [... query output goes here ...]
运行权限提升预设查询,跳过报告当前“admin”用户:
$ pmapper --account 000000000000 query -s 'preset privesc *' # [... privesc report goes here ...]
针对目标账号为创建一个SVG格式的可视化访问图:
$ pmapper --account 000000000000 visualize --filetype svg # [... information output goes here, file created ...]
下面给出的是可视化有向图的实例:
使用--only-privesc命令生成的结果如下:
输出样例
拉取一张图:
esteringer@ubuntu:~/Documents/projects/Skywalker$ python pmapper.py graph Using profile: skywalker Pulling data for account [REDACTED] Using principal with ARN arn:aws:iam::[REDACTED]:user/TestingSkywalker [+] Starting EC2 checks. [+] Starting IAM checks. [+] Starting Lambda checks. [+] Starting CloudFormation checks. [+] Completed CloudFormation checks. [+] Completed EC2 checks. [+] Completed Lambda checks. [+] Completed IAM checks. Created an AWS Graph with 16 nodes and 53 edges [NODES] AWSNode("arn:aws:iam::[REDACTED]:user/AdminUser", properties={u'is_admin': True, u'type': u'user'}) AWSNode("arn:aws:iam::[REDACTED]:user/EC2Manager", properties={u'is_admin': False, u'type': u'user'}) AWSNode("arn:aws:iam::[REDACTED]:user/LambdaDeveloper", properties={u'is_admin': False, u'type': u'user'}) AWSNode("arn:aws:iam::[REDACTED]:user/LambdaFullAccess", properties={u'is_admin': False, u'type': u'user'}) AWSNode("arn:aws:iam::[REDACTED]:user/PowerUser", properties={u'is_admin': False, u'rootstr': u'arn:aws:iam::[REDACTED]:root', u'type': u'user'}) AWSNode("arn:aws:iam::[REDACTED]:user/S3ManagementUser", properties={u'is_admin': False, u'type': u'user'}) AWSNode("arn:aws:iam::[REDACTED]:user/S3ReadOnly", properties={u'is_admin': False, u'type': u'user'}) AWSNode("arn:aws:iam::[REDACTED]:user/TestingSkywalker", properties={u'is_admin': False, u'type': u'user'}) AWSNode("arn:aws:iam::[REDACTED]:role/AssumableRole", properties={u'is_admin': False, u'type': u'role', u'name': u'AssumableRole'}) AWSNode("arn:aws:iam::[REDACTED]:role/EC2-Fleet-Manager", properties={u'is_admin': False, u'type': u'role', u'name': u'EC2-Fleet-Manager'}) AWSNode("arn:aws:iam::[REDACTED]:role/EC2Role-Admin", properties={u'is_admin': True, u'type': u'role', u'name': u'EC2Role-Admin'}) AWSNode("arn:aws:iam::[REDACTED]:role/EC2WithS3ReadOnly", properties={u'is_admin': False, u'type': u'role', u'name': u'EC2WithS3ReadOnly'}) AWSNode("arn:aws:iam::[REDACTED]:role/EMR-Service-Role", properties={u'is_admin': False, u'type': u'role', u'name': u'EMR-Service-Role'}) AWSNode("arn:aws:iam::[REDACTED]:role/LambdaRole-S3ReadOnly", properties={u'is_admin': False, u'type': u'role', u'name': u'LambdaRole-S3ReadOnly'}) AWSNode("arn:aws:iam::[REDACTED]:role/ReadOnlyWithLambda", properties={u'is_admin': False, u'type': u'role', u'name': u'ReadOnlyWithLambda'}) AWSNode("arn:aws:iam::[REDACTED]:role/UpdateCredentials", properties={u'is_admin': False, u'type': u'role', u'name': u'UpdateCredentials'}) [EDGES] (0,1,'ADMIN','can use existing administrative privileges to access') (0,2,'ADMIN','can use existing administrative privileges to access') (0,3,'ADMIN','can use existing administrative privileges to access') (0,4,'ADMIN','can use existing administrative privileges to access') (0,5,'ADMIN','can use existing administrative privileges to access') (0,6,'ADMIN','can use existing administrative privileges to access') (0,7,'ADMIN','can use existing administrative privileges to access') (0,8,'ADMIN','can use existing administrative privileges to access') (0,9,'ADMIN','can use existing administrative privileges to access') (0,10,'ADMIN','can use existing administrative privileges to access') (0,11,'ADMIN','can use existing administrative privileges to access') (0,12,'ADMIN','can use existing administrative privileges to access') (0,13,'ADMIN','can use existing administrative privileges to access') (0,14,'ADMIN','can use existing administrative privileges to access') (0,15,'ADMIN','can use existing administrative privileges to access') (10,0,'ADMIN','can use existing administrative privileges to access') (10,1,'ADMIN','can use existing administrative privileges to access') (10,2,'ADMIN','can use existing administrative privileges to access') (10,3,'ADMIN','can use existing administrative privileges to access') (10,4,'ADMIN','can use existing administrative privileges to access') (10,5,'ADMIN','can use existing administrative privileges to access') (10,6,'ADMIN','can use existing administrative privileges to access') (10,7,'ADMIN','can use existing administrative privileges to access') (10,8,'ADMIN','can use existing administrative privileges to access') (10,9,'ADMIN','can use existing administrative privileges to access') (10,11,'ADMIN','can use existing administrative privileges to access') (10,12,'ADMIN','can use existing administrative privileges to access') (10,13,'ADMIN','can use existing administrative privileges to access') (10,14,'ADMIN','can use existing administrative privileges to access') (10,15,'ADMIN','can use existing administrative privileges to access') (1,9,'EC2_USEPROFILE','can create an EC2 instance and use an existing instance profile to access') (1,10,'EC2_USEPROFILE','can create an EC2 instance and use an existing instance profile to access') (1,11,'EC2_USEPROFILE','can create an EC2 instance and use an existing instance profile to access') (4,9,'EC2_USEPROFILE','can create an EC2 instance and use an existing instance profile to access') (4,10,'EC2_USEPROFILE','can create an EC2 instance and use an existing instance profile to access') (4,11,'EC2_USEPROFILE','can create an EC2 instance and use an existing instance profile to access') (3,13,'LAMBDA_CREATEFUNCTION','can create a Lambda function and pass an execution role to access') (3,14,'LAMBDA_CREATEFUNCTION','can create a Lambda function and pass an execution role to access') (3,15,'LAMBDA_CREATEFUNCTION','can create a Lambda function and pass an execution role to access') (9,10,'EC2_USEPROFILE','can create an EC2 instance and use an existing instance profile to access') (4,13,'LAMBDA_CREATEFUNCTION','can create a Lambda function and pass an execution role to access') (9,11,'EC2_USEPROFILE','can create an EC2 instance and use an existing instance profile to access') (4,8,'STS_ASSUMEROLE','can use STS to assume the role') (4,14,'LAMBDA_CREATEFUNCTION','can create a Lambda function and pass an execution role to access') (4,15,'LAMBDA_CREATEFUNCTION','can create a Lambda function and pass an execution role to access') (15,0,'IAM_CREATEKEY','can create access keys with IAM to access') (15,1,'IAM_CREATEKEY','can create access keys with IAM to access') (15,2,'IAM_CREATEKEY','can create access keys with IAM to access') (15,3,'IAM_CREATEKEY','can create access keys with IAM to access') (15,4,'IAM_CREATEKEY','can create access keys with IAM to access') (15,5,'IAM_CREATEKEY','can create access keys with IAM to access') (15,6,'IAM_CREATEKEY','can create access keys with IAM to access') (15,7,'IAM_CREATEKEY','can create access keys with IAM to access')
查询图信息:
esteringer@ubuntu:~/Documents/projects/Skywalker$ ./pmapper.py --profile skywalker query "who can do s3:GetObject with *" user/AdminUser can do s3:GetObject with * user/EC2Manager can do s3:GetObject with * through role/EC2Role-Admin user/EC2Manager can create an EC2 instance and use an existing instance profile to access role/EC2Role-Admin role/EC2Role-Admin can do s3:GetObject with * user/LambdaFullAccess can do s3:GetObject with * user/PowerUser can do s3:GetObject with * user/S3ManagementUser can do s3:GetObject with * user/S3ReadOnly can do s3:GetObject with * user/TestingSkywalker can do s3:GetObject with * role/EC2-Fleet-Manager can do s3:GetObject with * through role/EC2Role-Admin role/EC2-Fleet-Manager can create an EC2 instance and use an existing instance profile to access role/EC2Role-Admin role/EC2Role-Admin can do s3:GetObject with * role/EC2Role-Admin can do s3:GetObject with * role/EC2WithS3ReadOnly can do s3:GetObject with * role/EMR-Service-Role can do s3:GetObject with * role/LambdaRole-S3ReadOnly can do s3:GetObject with * role/UpdateCredentials can do s3:GetObject with * through user/AdminUser role/UpdateCredentials can create access keys with IAM to access user/AdminUser user/AdminUser can do s3:GetObject with *
识别潜在的权限提升:
esteringer@ubuntu:~/Documents/projects/Skywalker$ ./pmapper.py --profile skywalker query "preset priv_esc user/PowerUser" Discovered a potential path to change privileges: user/PowerUser can change privileges because: user/PowerUser can access role/EC2Role-Admin because: user/PowerUser can create an EC2 instance and use an existing instance profile to access role/EC2Role-Admin and role/EC2Role-Admin can change its own privileges.
许可证协议
本项目的开发与发布遵循AGPL-3.0开源许可协议。
项目地址
PMapper:【GitHub传送门】