-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from PaloAltoNetworks/scen-4
Scenario 4 Updates
- Loading branch information
Showing
8 changed files
with
292 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"AMI ID": "ami-0eb9e8e8004581f2f", | ||
"Attacker Server Instance ID": "i-0877167aef7ac90db", | ||
"Attacker Server Public IP": "65.2.31.80", | ||
"Attacker Server Role": "my-instance-profile-d35bf34", | ||
"Key Pair Name": "my-key-pair-bd293a2", | ||
"Region": "ap-south-1", | ||
"Subnet ID": "subnet-0f82b1bdf83f603e7", | ||
"Victim Server Instance ID": "i-0eee1fd0b30ce2200", | ||
"Victim Server Public IP": "13.233.140.205", | ||
"Victim Server Role": "my-instance-profile-2-b681d68", | ||
"policy_name": "ec2-role-policy-afede80", | ||
"role_name": "ec2-role-0860d0b", | ||
"security_group_name": "web-sg-c2e6010" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
name: infra | ||
runtime: | ||
name: python | ||
options: | ||
virtualenv: ../../../venv | ||
description: A minimal AWS Python Pulumi program | ||
config: | ||
pulumi:tags: | ||
value: | ||
pulumi:template: "" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import pulumi | ||
import pulumi_aws as aws | ||
import os | ||
import sys | ||
import subprocess | ||
|
||
def read_public_key(pub_key_path): | ||
with open(pub_key_path, "r") as f: | ||
public_key = f.read().strip() | ||
|
||
return public_key | ||
|
||
current = aws.get_region() | ||
|
||
key_pair = aws.ec2.KeyPair("my-key-pair", public_key=read_public_key("../../../id_rsa.pub")) | ||
|
||
ubuntu_ami = aws.ec2.get_ami( | ||
filters=[ | ||
aws.ec2.GetAmiFilterArgs( | ||
name="name", | ||
values=["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"], | ||
), | ||
aws.ec2.GetAmiFilterArgs( | ||
name="virtualization-type", | ||
values=["hvm"], | ||
), | ||
], | ||
owners=["099720109477"], | ||
most_recent=True, | ||
|
||
) | ||
|
||
# Create an IAM role for EC2 instance | ||
role = aws.iam.Role("ec2-role", | ||
assume_role_policy="""{ | ||
"Version": "2012-10-17", | ||
"Statement": [{ | ||
"Effect": "Allow", | ||
"Principal": { | ||
"Service": "ec2.amazonaws.com" | ||
}, | ||
"Action": "sts:AssumeRole" | ||
}] | ||
}""" | ||
) | ||
|
||
# Attach a policy to the role allowing necessary permissions | ||
policy = aws.iam.RolePolicy("ec2-role-policy", | ||
role=role.name, | ||
policy="""{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Sid": "VisualEditor0", | ||
"Effect": "Allow", | ||
"Action": [ | ||
"ec2:StartInstances", | ||
"ec2:StopInstances", | ||
"ec2:ModifyInstanceAttribute" | ||
], | ||
"Resource": "*" | ||
} | ||
] | ||
}""" | ||
) | ||
|
||
role_2 = aws.iam.Role("ec2-role-imdsv2", | ||
assume_role_policy="""{ | ||
"Version": "2012-10-17", | ||
"Statement": [{ | ||
"Effect": "Allow", | ||
"Principal": { | ||
"Service": "ec2.amazonaws.com" | ||
}, | ||
"Action": "sts:AssumeRole" | ||
}] | ||
}""" | ||
) | ||
|
||
policy_2 = aws.iam.RolePolicy("server-role-policy", | ||
role=role_2.name, | ||
policy="""{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Sid": "VisualEditor0", | ||
"Effect": "Allow", | ||
"Action": [ | ||
"ec2:*", | ||
"s3:*" | ||
], | ||
"Resource": "*" | ||
} | ||
] | ||
}""" | ||
) | ||
|
||
sg = aws.ec2.SecurityGroup("web-sg", | ||
ingress=[ | ||
{ | ||
"protocol": "tcp", | ||
"fromPort": 8080, | ||
"toPort": 8080, | ||
"cidrBlocks": ["0.0.0.0/0"] | ||
}, | ||
{ | ||
"protocol": "tcp", | ||
"fromPort": 22, | ||
"toPort": 22, | ||
"cidrBlocks": ["0.0.0.0/0"] | ||
} | ||
], | ||
egress=[{ | ||
"protocol": "-1", | ||
"fromPort": 0, | ||
"toPort": 0, | ||
"cidrBlocks": ["0.0.0.0/0"] | ||
}] | ||
) | ||
|
||
# User data script to be executed when the instance starts | ||
user_data_script = """ | ||
IyEvYmluL2Jhc2gKc3VkbyBhcHQgaW5zdGFsbCBhd3NjbGkgLXkKd2dldCAtUCAvaG9tZS91YnVudHUvIGh0dHBzOi8vbGFiLWZpbGVzLTAwZmZhYWJjYy5zMy5hbWF6b25hd3MuY29tL3VlYmEtbGFiL3NlcnZlci5weQpzdWRvIGNob3duIHVidW50dTp1YnVudHUgL2hvbWUvdWJ1bnR1L3NlcnZlci5weQp3Z2V0IC1QIC9ob21lL3VidW50dS8gaHR0cHM6Ly9sYWItZmlsZXMtMDBmZmFhYmNjLnMzLmFtYXpvbmF3cy5jb20vdWViYS1sYWIvdXNlcmRhdGEudHh0Cg== | ||
""" | ||
|
||
instance_profile = aws.iam.InstanceProfile("my-instance-profile", | ||
role=role.name | ||
) | ||
|
||
instance_profile_2 = aws.iam.InstanceProfile("my-instance-profile-2", | ||
role=role_2.name | ||
) | ||
|
||
# Create an EC2 instance with user data | ||
instance = aws.ec2.Instance("attacker", | ||
instance_type="t2.micro", | ||
ami=ubuntu_ami.id, | ||
iam_instance_profile=instance_profile.name, | ||
security_groups=[sg.name], | ||
user_data=user_data_script, | ||
key_name=key_pair.key_name | ||
) | ||
|
||
instance1 = aws.ec2.Instance("imds-machine", | ||
instance_type="t2.micro", | ||
ami=ubuntu_ami.id, | ||
iam_instance_profile=instance_profile_2.name, | ||
security_groups=[sg.name], | ||
key_name=key_pair.key_name) | ||
|
||
|
||
# Export the public IP of the EC2 instance | ||
print("Attacker Server Public IP") | ||
pulumi.export("Attacker Server Public IP", instance.public_ip) | ||
|
||
print("Victim Server Public IP") | ||
pulumi.export("Victim Server Public IP", instance1.public_ip) | ||
|
||
pulumi.export("role_name", role.name) | ||
|
||
# Export the policy name | ||
pulumi.export("policy_name", policy.name) | ||
|
||
# Export the security group name | ||
pulumi.export("security_group_name", sg.name) | ||
|
||
# Export the instance profile name | ||
print("Attacker Server Role") | ||
pulumi.export("Attacker Server Role", instance_profile.name) | ||
|
||
print("Victim Server Role") | ||
pulumi.export("Victim Server Role", instance_profile_2.name) | ||
|
||
# Export the instance ID | ||
print("Attacker Server Instance ID") | ||
pulumi.export("Attacker Server Instance ID", instance.id) | ||
|
||
print("Victim Server Instance ID") | ||
pulumi.export("Victim Server Instance ID", instance1.id) | ||
|
||
pulumi.export("AMI ID", ubuntu_ami.id) | ||
|
||
pulumi.export("Subnet ID", instance.subnet_id) | ||
|
||
pulumi.export("Key Pair Name", key_pair.key_name) | ||
|
||
pulumi.export("Region", current.name) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import os | ||
import pyfiglet | ||
import time | ||
import subprocess | ||
import json | ||
from tqdm import tqdm | ||
from time import sleep | ||
from termcolor import colored | ||
from core.helpers import generate_ssh_key | ||
from core.helpers import loading_animation | ||
from core.helpers import generate_ssh_key | ||
|
||
def scenario_4_execute(): | ||
print("-"*30) | ||
print(colored("Executing Scenraio 4 : Exfiltrate EC2 role credentials using IMDSv2 with least privileged access", color="red")) | ||
loading_animation() | ||
print("-"*30) | ||
|
||
print(colored("Rolling out Infra", color="red")) | ||
loading_animation() | ||
print("-"*30) | ||
|
||
file_path = "./core/aws-scenario-3-output.json" | ||
if os.path.exists(file_path): | ||
os.remove(file_path) | ||
print("File '{}' found and deleted.".format(file_path)) | ||
else: | ||
print("File '{}' not found.".format(file_path)) | ||
|
||
generate_ssh_key() | ||
|
||
subprocess.call("cd ./scenarios/scenario_4/infra/ && pulumi up -s aws-scenario-3 -y", shell=True) | ||
subprocess.call("cd ./scenarios/scenario_4/infra/ && pulumi stack -s aws-scenario-3 output --json >> ../../../core/aws-scenario-3-output.json", shell=True) | ||
|
||
with open("./core/aws-scenario-3-output.json", "r") as file: | ||
data = json.load(file) | ||
|
||
ATTACKER_SERVER_PUBLIC_IP = data["Attacker Server Public IP"] | ||
VICTIM_SERVER_PUBLIC_IP = data["Victim Server Public IP"] | ||
ATTACKER_SERVER_INSTANCE_ID = data["Attacker Server Instance ID"] | ||
VICTIM_SERVER_INSTANCE_ID = data["Victim Server Instance ID"] | ||
SUBNET_ID = data["Subnet ID"] | ||
AMI_ID = data["AMI ID"] | ||
KEY_PAIR_NAME = data["Key Pair Name"] | ||
REGION = data["Region"] | ||
|
||
sleep_duration = 30 | ||
with tqdm(total=sleep_duration, desc="Loading") as pbar: | ||
while sleep_duration > 0: | ||
sleep_interval = min(1, sleep_duration) | ||
sleep(sleep_interval) | ||
|
||
pbar.update(sleep_interval) | ||
sleep_duration -= sleep_interval | ||
|
||
subprocess.call("ssh -o 'StrictHostKeyChecking accept-new' -i ./id_rsa ubuntu@"+ATTACKER_SERVER_PUBLIC_IP+" 'cat /etc/hostname'", shell=True) | ||
|
||
|
||
|