關于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 PMapperpip install .
Docker使用
將項目源碼克隆至本地之后,切換到項目目錄中,并執行下列命令:
cd PMapperdocker 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-Adminuser/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-Adminrole/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/AdminUserrole/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-Adminand role/EC2Role-Admin can change its own privileges.
許可證協議
本項目的開發與發布遵循AGPL-3.0開源許可協議。
項目地址
PMapper:【GitHub傳送門】