Description: This template deploys a VPC, with a pair of public and private subnets in a single Availability Zones. It deploys an internet gateway, with a default route on the public subnets. It also deploys a NAT gateway, and default route private subnets. Mappings: RegionMap: us-east-1: #North Virginia DvwaAMI: ami-09e67e426f25ce0d7 al2: ami-061ac2e015473fbe2 Ransomware: ami-08ed5c5dd62794ec0 BastionLinuxAMI: ami-09e67e426f25ce0d7 PrivateLinuxAMI: ami-09e67e426f25ce0d7 us-east-2: #Ohio DvwaAMI: ami-00399ec92321828f5 al2: ami-056b1936002ca8ede BastionLinuxAMI: ami-00399ec92321828f5 PrivateLinuxAMI: ami-00399ec92321828f5 us-west-1: #North California DvwaAMI: ami-0d382e80be7ffdae5 al2: ami-028f2b5ee08012131 BastionLinuxAMI: ami-0d382e80be7ffdae5 PrivateLinuxAMI: ami-0d382e80be7ffdae5 us-west-2: #Oregon DvwaAMI: ami-03d5c68bab01f3496 al2: ami-0e21d4d9303512b8e BastionLinuxAMI: ami-03d5c68bab01f3496 PrivateLinuxAMI: ami-03d5c68bab01f3496 Parameters: EnvironmentName: Description: An environment name that is prefixed to resource names Type: String Default: C1WS-labenvironment InspectionVPCCIDR: Description: Please enter the IP range (CIDR notation) for this INSPECTION VPC Type: String Default: 10.10.0.0/16 ProtectedPublicSubnetCIDR: Description: Please enter the IP range (CIDR notation) for the PROTECTED-PUBLIC subnet Type: String Default: 10.10.10.0/24 ProtectedPublicSubnetAZ: Description: Please enter the Availability Zone that you want to use for the PROTECTED-PUBLIC subnet Type: String Default: us-east-1a ProtectedPrivateSubnetCIDR: Description: Please enter the IP range (CIDR notation) for the PROTECTED-PRIVATE subnet Type: String Default: 10.10.20.0/24 ProtectedPrivateSubnetAZ: Description: Please enter the Availability Zone that you want to use for the PROTECTED-PRIVATE subnet Type: String Default: us-east-1a KeyPair: Description: Please enter the valid Key Pair for your region Type: String MyPublicIP: Description: Please enter your public IP with CIDR (e.g. 191.162.228.91/32). As a example you can use https://wtfismyip.com/text or https://ipinfo.io/ip . It will be use to allow you to access the DVWA through HTTP (TCP/80). Type: String Resources: #Creating VPC that will be using in the demo environment VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref InspectionVPCCIDR EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Sub Inpection VPC - ${EnvironmentName} - Key: VPC Name Value: Inpection VPC - Key: Service Value: Cloud One Network Security #creating an Internet Gateway InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Sub IGW - ${EnvironmentName} - Key: Service Value: Cloud One #Attaching the Internet Gateway to the VPC that we create InternetGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC #Creating the Protected-Public Subnet ProtectedPublicSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: !Ref ProtectedPublicSubnetCIDR MapPublicIpOnLaunch: true Tags: - Key: Name Value: !Sub Protected-Public Subnet ${EnvironmentName} #Creating the Protected-Private Subnet ProtectedPrivateSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC AvailabilityZone: !Select [ 0, !GetAZs '' ] CidrBlock: !Ref ProtectedPrivateSubnetCIDR MapPublicIpOnLaunch: false Tags: - Key: Name Value: !Sub Protected-Private Subnet ${EnvironmentName} #Creating the Elastic IP for the NAT Gateway NatGatewayEIP: Type: AWS::EC2::EIP DependsOn: InternetGatewayAttachment Properties: Domain: vpc #Creating the NAT Gateway that will be use in the Protected-Public Subnet NatGateway: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NatGatewayEIP.AllocationId SubnetId: !Ref ProtectedPublicSubnet #Creating the Public Route table PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub Protected Public Routes - ${EnvironmentName} #Add a default route in the Public Route table DefaultPublicRoute: Type: AWS::EC2::Route DependsOn: InternetGatewayAttachment Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway #Associating the Protected-Public Subnet in the Public Route Table (Edge Association) ProtectedPublicSubnetRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref ProtectedPublicSubnet #Creating the Private Route table PrivateRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Sub Private Routes - ${EnvironmentName} #Add a default route in the Private Route table DefaultPrivateRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NatGateway #Associating the Protected-Private Subnet in the Private Route Table ProtectedPrivateSubnetRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable SubnetId: !Ref ProtectedPrivateSubnet #Creating the Security Gorup for Allowing only inbound traffic from the VPC CIDR and any outbound traffic. NoIngressSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: "no-ingress-sg" GroupDescription: "Security group with no ingress rule" VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 10.10.0.0/16 - IpProtocol: tcp FromPort: 3389 ToPort: 3389 CidrIp: 10.10.0.0/16 SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 #Creating the Security Gorup for Allowing SSH and RDP inbound traffic from any source IP, but for HTTP only if the source IP are in the VPC CIDR. Allowing any outbound traffic. #Note: If you want to acess the DVWA Application you can add a new entry here for your Public IP or you can add it later in the AWS Console. PublicAccessSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupName: "public-ingress-sg" GroupDescription: "Security group with no ingress rule" VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 10.10.0.0/16 - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: !Ref MyPublicIP - IpProtocol: tcp FromPort: 8080 ToPort: 8080 CidrIp: 10.10.0.0/16 - IpProtocol: tcp FromPort: 8080 ToPort: 8080 CidrIp: !Ref MyPublicIP - IpProtocol: tcp FromPort: 8888 ToPort: 8888 CidrIp: 10.10.0.0/16 - IpProtocol: tcp FromPort: 8888 ToPort: 8888 CidrIp: !Ref MyPublicIP - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 3389 ToPort: 3389 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 0 ToPort: 65535 CidrIp: 0.0.0.0/0 #EC2 Role to be assumed and use to create the EC2 resources also allows ssm deployment. EC2Role: Type: 'AWS::IAM::Role' Properties: RoleName: !Sub "EC2Role-${EnvironmentName}" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - ec2.amazonaws.com Action: - "sts:AssumeRole" ManagedPolicyArns: - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore #Instance profile EC2InstanceProfile: Type: 'AWS::IAM::InstanceProfile' Properties: Path: / Roles: - !Ref EC2Role #Creating the instance that will be a Linux Bastion Host. BastionLinux: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - BastionLinuxAMI InstanceType: t3.micro KeyName: !Ref KeyPair IamInstanceProfile: !Ref EC2InstanceProfile Tags: - Key: Name Value: BastionLinux - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPublicSubnet SecurityGroupIds: - Ref: PublicAccessSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 UserData: !Base64 | #!/bin/bash sudo apt update sleep 10 sudo apt install -y awscli #Creating the instance that will be a Windows Bastion Host. RanSimWin: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - Ransomware InstanceType: t2.medium KeyName: !Ref KeyPair IamInstanceProfile: !Ref EC2InstanceProfile Tags: - Key: Name Value: RansomServer - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPublicSubnet SecurityGroupIds: - Ref: PublicAccessSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 UserData: !Base64 | msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) choco install -y git -Wait $Env:Path += ";C:\Program Files\Git\cmd" choco install -y go -Wait choco install -y make -Wait Set-MpPreference -DisableRealtimeMonitoring $true $AdminKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}" $UserKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A8-37EF-4b3f-8CFC-4F3A74704073}" Set-ItemProperty -Path $AdminKey -Name "IsInstalled" -Value 0 Set-ItemProperty -Path $UserKey -Name "IsInstalled" -Value 0 cd\ cd Users\Administrator\Desktop git clone https://github.com/NextronSystems/ransomware-simulator.git #Creating the instance that will the DVWA host. Note that the DVWA will run as container. DVWA: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - DvwaAMI InstanceType: t3.micro KeyName: !Ref KeyPair IamInstanceProfile: !Ref EC2InstanceProfile Tags: - Key: Name Value: DVWA - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPublicSubnet SecurityGroupIds: - Ref: PublicAccessSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 UserData: !Base64 | #!/bin/bash sudo apt update sleep 10 sudo apt install -y awscli apt install -y apt-transport-https ca-certificates curl gnupg python3-pip lsb-release sleep 60 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg sleep 10 echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null apt update sleep 10 apt install -y docker-ce docker-ce-cli containerd.io sleep 60 docker run --rm -it -d -p 80:80 vulnerables/web-dvwa #Creating the instance that will be a Log4shell demonstration. Log4VulnerableServer: Type: AWS::EC2::Instance Properties: SubnetId: !Ref ProtectedPublicSubnet IamInstanceProfile: !Ref EC2InstanceProfile SecurityGroupIds: - Ref: PublicAccessSecurityGroup ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", al2] KeyName: !Ref KeyPair InstanceType: t2.medium UserData: !Base64 | #!/bin/bash sudo yum update -y sudo yum install -y git sudo amazon-linux-extras install -y docker sudo service docker start sudo amazon-linux-extras install -y java-openjdk11 cd home/ec2-user git clone https://github.com/christophetd/log4shell-vulnerable-app.git wget https://aws-workshop-c1as-cft-templates.s3.amazonaws.com/JNDIExploit.v1.2.zip cd log4shell-vulnerable-app sudo docker build . -t vulnerable-app docker run -p 8080:8080 --name vulnerable-app vulnerable-app Tags: - Key: Name Value: Log4 - Key: Project Value: Cloud One Demo Lab #Creating the instance that will be a Linux machine in the Protected-Private Subnet. PrivateLinux: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - RegionMap - Ref: AWS::Region - PrivateLinuxAMI InstanceType: t3.small KeyName: !Ref KeyPair IamInstanceProfile: !Ref EC2InstanceProfile Tags: - Key: Name Value: PrivateLinux - Key: Project Value: Cloud One Demo Lab SubnetId: !Ref ProtectedPrivateSubnet SecurityGroupIds: - Ref: NoIngressSecurityGroup BlockDeviceMappings: - DeviceName: /dev/sdm Ebs: DeleteOnTermination: true VolumeSize: 20 UserData: !Base64 | #!/bin/bash sudo apt update sleep 10 sudo apt install -y awscli #Outputs to be presented in the CloudFormation Stack Outputs: VPC: Description: A reference to the created VPC Value: !Ref VPC ProtectedPublicSubnet: Description: A reference to the public subnet in the 1st Availability Zone Value: !Ref ProtectedPublicSubnet ProtectedPrivateSubnet: Description: A reference to the private subnet in the 1st Availability Zone Value: !Ref ProtectedPrivateSubnet NoIngressSecurityGroup: Description: Security group with no ingress rule Value: !Ref NoIngressSecurityGroup DVWAPublicDNSName: Description: Export the DVWA instance Public DNS Name Value: !GetAtt DVWA.PublicDnsName BastionLinuxPublicDNSName: Description: Export the Bastion instance Public DNS Name Value: !GetAtt BastionLinux.PublicDnsName Log4VulnerableServerPublicDnsName: Description: Export the Log4Shell instance Public DNS Name Value: !GetAtt Log4VulnerableServer.PublicDnsName Log4VulnerableServerPrivateDnsName: Description: Export the Log4Shell instance Private DNS Name Value: !GetAtt Log4VulnerableServer.PrivateDnsName