mirror of
https://github.com/BishopFox/cloudfoxable.git
synced 2026-11-07 09:56:00 -10:00
Merge pull request #37 from BishopFox/azure/new-challenges
Azure/new challenges
This commit is contained in:
30 files changed
+2066
-1
No files matched your search
+11
-1
@@ -46,5 +46,15 @@ response.json
|
||||
.ctf
|
||||
config
|
||||
|
||||
# challenge specific files
|
||||
azure/challenges/Cloud Jumping/data/container/tmp.txt
|
||||
azure/challenges/Image-ination Continuation/data/logicapp_identity.txt
|
||||
azure/challenges/Image-ination Station/data/sp-creds.json
|
||||
azure/challenges/Not so secret/data/assets.csv
|
||||
azure/challenges/Permisery/data/app.py
|
||||
azure/challenges/Permisery/data/requirements.txt
|
||||
azure/challenges/Permisery/zip/
|
||||
|
||||
|
||||
# other azure files
|
||||
azure/credentials.txt
|
||||
azure/terraform.tfvars
|
||||
@@ -0,0 +1,282 @@
|
||||
# resource group
|
||||
resource "azurerm_resource_group" "cloudjumping" {
|
||||
name = "cloudjumpingRG"
|
||||
location = var.azure_region
|
||||
}
|
||||
|
||||
data "azuread_domains" "domain" {
|
||||
only_initial = true
|
||||
}
|
||||
|
||||
data "azurerm_subscription" "current" {}
|
||||
|
||||
data "http" "current_ip" {
|
||||
url = "https://icanhazip.com"
|
||||
}
|
||||
|
||||
locals {
|
||||
user_ip = chomp(data.http.current_ip.response_body)
|
||||
}
|
||||
|
||||
# password for read user
|
||||
resource "random_password" "read_user_password" {
|
||||
length = 16
|
||||
special = true
|
||||
}
|
||||
|
||||
# store creds locally then later upload them to storage account
|
||||
resource "local_file" "credentials" {
|
||||
filename = "${path.module}/data/container/tmp.txt"
|
||||
content = <<-EOF
|
||||
"az.reader@${data.azuread_domains.domain.domains.0.domain_name}"
|
||||
${random_password.read_user_password.result}
|
||||
EOF
|
||||
}
|
||||
|
||||
# create read user and give them global reader
|
||||
resource "azuread_user" "read_user" {
|
||||
user_principal_name = "az.reader@${data.azuread_domains.domain.domains.0.domain_name}"
|
||||
display_name = "Azure Reader"
|
||||
password = random_password.read_user_password.result
|
||||
}
|
||||
|
||||
resource "azuread_directory_role_assignment" "global_reader_assigment" {
|
||||
role_id = "f2ef992c-3afb-46b9-b7cf-a126ee74c451"
|
||||
principal_object_id = azuread_user.read_user.object_id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "subscription_reader_access" {
|
||||
scope = data.azurerm_subscription.current.id
|
||||
role_definition_name = "Reader"
|
||||
principal_id = azuread_user.read_user.object_id
|
||||
}
|
||||
|
||||
/*---------------------------------------------*/
|
||||
|
||||
|
||||
#################################################
|
||||
// Create publicly accessible blob container
|
||||
#################################################
|
||||
|
||||
resource "random_id" "challenge_instance_id" {
|
||||
byte_length = 4
|
||||
}
|
||||
|
||||
locals {
|
||||
uploaded_files = fileset("${path.module}/data/container", "*")
|
||||
}
|
||||
|
||||
resource "azurerm_storage_account" "sa" {
|
||||
name = "cloudjumping${random_id.challenge_instance_id.hex}"
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
location = azurerm_resource_group.cloudjumping.location
|
||||
account_tier = "Standard"
|
||||
account_replication_type = "LRS"
|
||||
allow_nested_items_to_be_public = true
|
||||
|
||||
network_rules {
|
||||
default_action = "Deny"
|
||||
bypass = ["AzureServices"]
|
||||
ip_rules = [
|
||||
local.user_ip
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_storage_container" "container" {
|
||||
name = "files"
|
||||
storage_account_id = azurerm_storage_account.sa.id
|
||||
container_access_type = "container"
|
||||
}
|
||||
|
||||
resource "azurerm_storage_blob" "blob" {
|
||||
for_each = { for file in local.uploaded_files : file => file }
|
||||
name = each.value
|
||||
storage_account_name = azurerm_storage_account.sa.name
|
||||
storage_container_name = azurerm_storage_container.container.name
|
||||
type = "Block"
|
||||
source = "${path.module}/data/container/${each.value}"
|
||||
}
|
||||
|
||||
# give player permissions to read storage account and data
|
||||
resource "azurerm_role_assignment" "storage_blob_reader" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Storage Blob Data Reader"
|
||||
scope = azurerm_storage_account.sa.id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "reader" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Reader"
|
||||
scope = azurerm_storage_account.sa.id
|
||||
}
|
||||
|
||||
/*---------------------------------------------*/
|
||||
|
||||
|
||||
#################################################
|
||||
// Create a managed identity
|
||||
#################################################
|
||||
|
||||
resource "azurerm_user_assigned_identity" "contributor_managed_identity" {
|
||||
name = "contributor-managed-identity"
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
location = azurerm_resource_group.cloudjumping.location
|
||||
}
|
||||
|
||||
# managed identity should have contributor role for cloudjumping resource group
|
||||
resource "azurerm_role_assignment" "contributor" {
|
||||
scope = azurerm_resource_group.cloudjumping.id
|
||||
role_definition_name = "Contributor"
|
||||
principal_id = azurerm_user_assigned_identity.contributor_managed_identity.principal_id
|
||||
}
|
||||
|
||||
/*---------------------------------------------*/
|
||||
|
||||
|
||||
#################################################
|
||||
// Create Linux VM with a managed identity
|
||||
#################################################
|
||||
|
||||
# vm1 (jump-host) gets deployed from a template
|
||||
data "local_file" "jump_host_template" {
|
||||
filename = "${path.module}/data/jump-host-template.json"
|
||||
}
|
||||
|
||||
resource "random_password" "jump_host_user_password" {
|
||||
length = 16
|
||||
special = true
|
||||
}
|
||||
|
||||
resource "azurerm_resource_group_template_deployment" "jump_host_vm" {
|
||||
name = "jump_host"
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
deployment_mode = "Incremental"
|
||||
template_content = data.local_file.jump_host_template.content
|
||||
parameters_content = jsonencode({
|
||||
adminPasswordOrKey = {
|
||||
value = random_password.jump_host_user_password.result
|
||||
}
|
||||
})
|
||||
|
||||
depends_on = [
|
||||
azurerm_role_assignment.contributor
|
||||
]
|
||||
}
|
||||
|
||||
/*---------------------------------------------*/
|
||||
|
||||
|
||||
#################################################
|
||||
// Create Linux VM with the flag
|
||||
#################################################
|
||||
|
||||
resource "random_password" "linux_vm_user_password" {
|
||||
length = 16
|
||||
special = true
|
||||
}
|
||||
|
||||
resource "azurerm_virtual_network" "linux_vm_vnet" {
|
||||
name = "production-vnet"
|
||||
address_space = ["10.2.0.0/16"]
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
location = azurerm_resource_group.cloudjumping.location
|
||||
}
|
||||
|
||||
resource "azurerm_subnet" "linux_vm_subnet" {
|
||||
name = "production-subnet"
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
virtual_network_name = azurerm_virtual_network.linux_vm_vnet.name
|
||||
address_prefixes = ["10.2.1.0/24"]
|
||||
}
|
||||
|
||||
resource "azurerm_public_ip" "linux_vm_ip" {
|
||||
name = "production-public-ip"
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
location = azurerm_resource_group.cloudjumping.location
|
||||
allocation_method = "Static"
|
||||
}
|
||||
|
||||
resource "azurerm_network_interface" "linux_vm_nic" {
|
||||
name = "production-vm-nic"
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
location = azurerm_resource_group.cloudjumping.location
|
||||
|
||||
ip_configuration {
|
||||
name = "internal"
|
||||
subnet_id = azurerm_subnet.linux_vm_subnet.id
|
||||
private_ip_address_allocation = "Dynamic"
|
||||
public_ip_address_id = azurerm_public_ip.linux_vm_ip.id
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
azurerm_public_ip.linux_vm_ip
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_network_security_group" "ctf_nsg" {
|
||||
name = "ctf-nsg"
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
location = azurerm_resource_group.cloudjumping.location
|
||||
|
||||
security_rule {
|
||||
name = "Allow-SSH"
|
||||
priority = 1001
|
||||
direction = "Inbound"
|
||||
access = "Allow"
|
||||
protocol = "Tcp"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "22"
|
||||
source_address_prefix = local.user_ip
|
||||
destination_address_prefix = "*"
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_subnet_network_security_group_association" "ctf_subnet_assoc" {
|
||||
subnet_id = azurerm_subnet.linux_vm_subnet.id
|
||||
network_security_group_id = azurerm_network_security_group.ctf_nsg.id
|
||||
}
|
||||
|
||||
resource "azurerm_linux_virtual_machine" "linux_vm" {
|
||||
name = "production-server"
|
||||
resource_group_name = azurerm_resource_group.cloudjumping.name
|
||||
location = azurerm_resource_group.cloudjumping.location
|
||||
size = "Standard_B1s"
|
||||
admin_username = "azureadmin"
|
||||
admin_password = random_password.linux_vm_user_password.result
|
||||
disable_password_authentication = false
|
||||
|
||||
network_interface_ids = [
|
||||
azurerm_network_interface.linux_vm_nic.id
|
||||
]
|
||||
|
||||
os_disk {
|
||||
caching = "ReadWrite"
|
||||
storage_account_type = "Standard_LRS"
|
||||
name = "production-server-disk"
|
||||
}
|
||||
|
||||
source_image_reference {
|
||||
publisher = "Canonical"
|
||||
offer = "0001-com-ubuntu-server-focal"
|
||||
sku = "20_04-lts"
|
||||
version = "latest"
|
||||
}
|
||||
|
||||
connection {
|
||||
type = "ssh"
|
||||
host = azurerm_public_ip.linux_vm_ip.ip_address
|
||||
user = "azureadmin"
|
||||
password = random_password.linux_vm_user_password.result
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
source = "${path.module}/data/flag.txt"
|
||||
destination = "/home/azureadmin/flag.txt"
|
||||
}
|
||||
|
||||
depends_on = [
|
||||
azurerm_public_ip.linux_vm_ip,
|
||||
azurerm_network_interface.linux_vm_nic
|
||||
]
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
FLAG{cloudJumping:justAnotherDayCloudJumping}
|
||||
@@ -0,0 +1,340 @@
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"metadata": {
|
||||
"_generator": {
|
||||
"name": "bicep",
|
||||
"version": "0.34.1.11899",
|
||||
"templateHash": "6608977399677963554"
|
||||
}
|
||||
},
|
||||
"parameters": {
|
||||
"vmName": {
|
||||
"type": "string",
|
||||
"defaultValue": "jump-host",
|
||||
"metadata": {
|
||||
"description": "The name of your Virtual Machine."
|
||||
}
|
||||
},
|
||||
"adminUsername": {
|
||||
"type": "string",
|
||||
"defaultValue": "azureuser",
|
||||
"metadata": {
|
||||
"description": "Username for the Virtual Machine."
|
||||
}
|
||||
},
|
||||
"authenticationType": {
|
||||
"type": "string",
|
||||
"defaultValue": "password",
|
||||
"allowedValues": [
|
||||
"sshPublicKey",
|
||||
"password"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Type of authentication to use on the Virtual Machine. SSH key is recommended."
|
||||
}
|
||||
},
|
||||
"adminPasswordOrKey": {
|
||||
"type": "string",
|
||||
"metadata": {
|
||||
"description": "SSH Key or password for the Virtual Machine. SSH key is recommended."
|
||||
}
|
||||
},
|
||||
"dnsLabelPrefix": {
|
||||
"type": "string",
|
||||
"defaultValue": "[toLower(format('{0}-{1}', parameters('vmName'), uniqueString(resourceGroup().id)))]",
|
||||
"metadata": {
|
||||
"description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
|
||||
}
|
||||
},
|
||||
"ubuntuOSVersion": {
|
||||
"type": "string",
|
||||
"defaultValue": "Ubuntu-2204",
|
||||
"allowedValues": [
|
||||
"Ubuntu-2004",
|
||||
"Ubuntu-2204"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "The Ubuntu version for the VM. This will pick a fully patched image of this given Ubuntu version."
|
||||
}
|
||||
},
|
||||
"location": {
|
||||
"type": "string",
|
||||
"defaultValue": "[resourceGroup().location]",
|
||||
"metadata": {
|
||||
"description": "Location for all resources."
|
||||
}
|
||||
},
|
||||
"vmSize": {
|
||||
"type": "string",
|
||||
"defaultValue": "Standard_B1s",
|
||||
"metadata": {
|
||||
"description": "The size of the VM"
|
||||
}
|
||||
},
|
||||
"virtualNetworkName": {
|
||||
"type": "string",
|
||||
"defaultValue": "vNet",
|
||||
"metadata": {
|
||||
"description": "Name of the VNET"
|
||||
}
|
||||
},
|
||||
"subnetName": {
|
||||
"type": "string",
|
||||
"defaultValue": "Subnet",
|
||||
"metadata": {
|
||||
"description": "Name of the subnet in the virtual network"
|
||||
}
|
||||
},
|
||||
"networkSecurityGroupName": {
|
||||
"type": "string",
|
||||
"defaultValue": "CJjumpHostSecGroup",
|
||||
"metadata": {
|
||||
"description": "Name of the Network Security Group"
|
||||
}
|
||||
},
|
||||
"securityType": {
|
||||
"type": "string",
|
||||
"defaultValue": "TrustedLaunch",
|
||||
"allowedValues": [
|
||||
"Standard",
|
||||
"TrustedLaunch"
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Security Type of the Virtual Machine."
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"imageReference": {
|
||||
"Ubuntu-2004": {
|
||||
"publisher": "Canonical",
|
||||
"offer": "0001-com-ubuntu-server-focal",
|
||||
"sku": "20_04-lts-gen2",
|
||||
"version": "latest"
|
||||
},
|
||||
"Ubuntu-2204": {
|
||||
"publisher": "Canonical",
|
||||
"offer": "0001-com-ubuntu-server-jammy",
|
||||
"sku": "22_04-lts-gen2",
|
||||
"version": "latest"
|
||||
}
|
||||
},
|
||||
"publicIPAddressName": "[format('{0}PublicIP', parameters('vmName'))]",
|
||||
"networkInterfaceName": "[format('{0}NetInt', parameters('vmName'))]",
|
||||
"osDiskType": "Standard_LRS",
|
||||
"subnetAddressPrefix": "10.1.0.0/24",
|
||||
"addressPrefix": "10.1.0.0/16",
|
||||
"linuxConfiguration": {
|
||||
"disablePasswordAuthentication": true,
|
||||
"ssh": {
|
||||
"publicKeys": [
|
||||
{
|
||||
"path": "[format('/home/{0}/.ssh/authorized_keys', parameters('adminUsername'))]",
|
||||
"keyData": "[parameters('adminPasswordOrKey')]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"securityProfileJson": {
|
||||
"uefiSettings": {
|
||||
"secureBootEnabled": true,
|
||||
"vTpmEnabled": true
|
||||
},
|
||||
"securityType": "[parameters('securityType')]"
|
||||
},
|
||||
"extensionName": "GuestAttestation",
|
||||
"extensionPublisher": "Microsoft.Azure.Security.LinuxAttestation",
|
||||
"extensionVersion": "1.0",
|
||||
"maaTenantName": "GuestAttestation",
|
||||
"maaEndpoint": "[substring('emptystring', 0, 0)]"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Network/networkInterfaces",
|
||||
"apiVersion": "2023-09-01",
|
||||
"name": "[variables('networkInterfaceName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"properties": {
|
||||
"ipConfigurations": [
|
||||
{
|
||||
"name": "ipconfig1",
|
||||
"properties": {
|
||||
"subnet": {
|
||||
"id": "[reference(resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName')), '2023-09-01').subnets[0].id]"
|
||||
},
|
||||
"privateIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddress": {
|
||||
"id": "[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"networkSecurityGroup": {
|
||||
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]"
|
||||
}
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]",
|
||||
"[resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName'))]",
|
||||
"[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Network/networkSecurityGroups",
|
||||
"apiVersion": "2023-09-01",
|
||||
"name": "[parameters('networkSecurityGroupName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"properties": {
|
||||
"securityRules": [
|
||||
{
|
||||
"name": "SSH",
|
||||
"properties": {
|
||||
"priority": 1000,
|
||||
"protocol": "Tcp",
|
||||
"access": "Allow",
|
||||
"direction": "Inbound",
|
||||
"sourceAddressPrefix": "*",
|
||||
"sourcePortRange": "*",
|
||||
"destinationAddressPrefix": "*",
|
||||
"destinationPortRange": "22"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Network/virtualNetworks",
|
||||
"apiVersion": "2023-09-01",
|
||||
"name": "[parameters('virtualNetworkName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"properties": {
|
||||
"addressSpace": {
|
||||
"addressPrefixes": [
|
||||
"[variables('addressPrefix')]"
|
||||
]
|
||||
},
|
||||
"subnets": [
|
||||
{
|
||||
"name": "[parameters('subnetName')]",
|
||||
"properties": {
|
||||
"networkSecurityGroup": {
|
||||
"id": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]"
|
||||
},
|
||||
"addressPrefix": "[variables('subnetAddressPrefix')]",
|
||||
"privateEndpointNetworkPolicies": "Enabled",
|
||||
"privateLinkServiceNetworkPolicies": "Enabled"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Network/publicIPAddresses",
|
||||
"apiVersion": "2023-09-01",
|
||||
"name": "[variables('publicIPAddressName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"sku": {
|
||||
"name": "Basic"
|
||||
},
|
||||
"properties": {
|
||||
"publicIPAllocationMethod": "Dynamic",
|
||||
"publicIPAddressVersion": "IPv4",
|
||||
"dnsSettings": {
|
||||
"domainNameLabel": "[parameters('dnsLabelPrefix')]"
|
||||
},
|
||||
"idleTimeoutInMinutes": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Compute/virtualMachines",
|
||||
"apiVersion": "2023-09-01",
|
||||
"name": "[parameters('vmName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"identity": {
|
||||
"type": "UserAssigned",
|
||||
"userAssignedIdentities": {
|
||||
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'contributor-managed-identity')]": {}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"hardwareProfile": {
|
||||
"vmSize": "[parameters('vmSize')]"
|
||||
},
|
||||
"storageProfile": {
|
||||
"osDisk": {
|
||||
"createOption": "FromImage",
|
||||
"deleteOption": "Delete",
|
||||
"managedDisk": {
|
||||
"storageAccountType": "[variables('osDiskType')]"
|
||||
}
|
||||
},
|
||||
"imageReference": "[variables('imageReference')[parameters('ubuntuOSVersion')]]"
|
||||
},
|
||||
"networkProfile": {
|
||||
"networkInterfaces": [
|
||||
{
|
||||
"id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]"
|
||||
}
|
||||
]
|
||||
},
|
||||
"osProfile": {
|
||||
"computerName": "[parameters('vmName')]",
|
||||
"adminUsername": "[parameters('adminUsername')]",
|
||||
"adminPassword": "[parameters('adminPasswordOrKey')]",
|
||||
"linuxConfiguration": "[if(equals(parameters('authenticationType'), 'password'), null(), variables('linuxConfiguration'))]"
|
||||
},
|
||||
"securityProfile": "[if(equals(parameters('securityType'), 'TrustedLaunch'), variables('securityProfileJson'), null())]"
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Network/networkInterfaces', variables('networkInterfaceName'))]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"condition": "[and(and(equals(parameters('securityType'), 'TrustedLaunch'), variables('securityProfileJson').uefiSettings.secureBootEnabled), variables('securityProfileJson').uefiSettings.vTpmEnabled)]",
|
||||
"type": "Microsoft.Compute/virtualMachines/extensions",
|
||||
"apiVersion": "2023-09-01",
|
||||
"name": "[format('{0}/{1}', parameters('vmName'), variables('extensionName'))]",
|
||||
"location": "[parameters('location')]",
|
||||
"properties": {
|
||||
"publisher": "[variables('extensionPublisher')]",
|
||||
"type": "[variables('extensionName')]",
|
||||
"typeHandlerVersion": "[variables('extensionVersion')]",
|
||||
"autoUpgradeMinorVersion": true,
|
||||
"enableAutomaticUpgrade": true,
|
||||
"settings": {
|
||||
"AttestationConfig": {
|
||||
"MaaSettings": {
|
||||
"maaEndpoint": "[variables('maaEndpoint')]",
|
||||
"maaTenantName": "[variables('maaTenantName')]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Compute/virtualMachines', parameters('vmName'))]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": {
|
||||
"adminUsername": {
|
||||
"type": "string",
|
||||
"value": "[parameters('adminUsername')]"
|
||||
},
|
||||
"adminPassword": {
|
||||
"type": "string",
|
||||
"value": "[parameters('adminPasswordOrKey')]"
|
||||
},
|
||||
"hostname": {
|
||||
"type": "string",
|
||||
"value": "[reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName')), '2023-09-01').dnsSettings.fqdn]"
|
||||
},
|
||||
"sshCommand": {
|
||||
"type": "string",
|
||||
"value": "[format('ssh {0}@{1}', parameters('adminUsername'), reference(resourceId('Microsoft.Network/publicIPAddresses', variables('publicIPAddressName')), '2023-09-01').dnsSettings.fqdn)]"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
variable "azure_region" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_upn" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_object_id" {
|
||||
type = string
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
# resource group
|
||||
resource "azurerm_resource_group" "imageinationcontinuation" {
|
||||
name = "imageinationcontinuationRG"
|
||||
location = var.azure_region
|
||||
}
|
||||
|
||||
resource "random_id" "suffix" {
|
||||
byte_length = 4
|
||||
}
|
||||
|
||||
resource "random_password" "sp_pwd" {
|
||||
length = 20
|
||||
special = true
|
||||
}
|
||||
|
||||
data "azurerm_client_config" "current" {}
|
||||
|
||||
# create a key vault
|
||||
resource "azurerm_key_vault" "ctf" {
|
||||
name = "ctfkv${random_id.suffix.hex}"
|
||||
resource_group_name = azurerm_resource_group.imageinationcontinuation.name
|
||||
location = azurerm_resource_group.imageinationcontinuation.location
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
sku_name = "standard"
|
||||
purge_protection_enabled = false
|
||||
enable_rbac_authorization = true
|
||||
}
|
||||
|
||||
# place the flag in the key vault
|
||||
resource "azurerm_key_vault_secret" "flag" {
|
||||
name = "flag"
|
||||
value = "Flag{imageinationContinuation:protectThoseServicePrincipalCreds}"
|
||||
key_vault_id = azurerm_key_vault.ctf.id
|
||||
|
||||
depends_on = [azurerm_role_assignment.kv_admin]
|
||||
}
|
||||
|
||||
# create an identity for the logic app
|
||||
resource "azurerm_user_assigned_identity" "logicapp_identity" {
|
||||
name = "logicapp-mi-${random_id.suffix.hex}"
|
||||
resource_group_name = azurerm_resource_group.imageinationcontinuation.name
|
||||
location = azurerm_resource_group.imageinationcontinuation.location
|
||||
}
|
||||
|
||||
locals {
|
||||
logicapp_name = "flag-logicapp-${random_id.suffix.hex}"
|
||||
}
|
||||
|
||||
# create a deployment template for the logic app
|
||||
resource "azurerm_resource_group_template_deployment" "logicapp_with_flag" {
|
||||
name = "logicapp-deploy-${random_id.suffix.hex}"
|
||||
resource_group_name = azurerm_resource_group.imageinationcontinuation.name
|
||||
deployment_mode = "Incremental"
|
||||
|
||||
template_content = jsonencode({
|
||||
"$schema" = "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion" = "1.0.0.0",
|
||||
"parameters" = {},
|
||||
"resources" = [
|
||||
{
|
||||
"type" = "Microsoft.Logic/workflows",
|
||||
"apiVersion" = "2019-05-01",
|
||||
"name" = "${local.logicapp_name}",
|
||||
"location" = azurerm_resource_group.imageinationcontinuation.location,
|
||||
"identity" = {
|
||||
"type" = "SystemAssigned"
|
||||
},
|
||||
"properties" = {
|
||||
"definition" = {
|
||||
"$schema" = "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
|
||||
"actions" = {
|
||||
"GetFlag" = {
|
||||
"type" = "Http",
|
||||
"inputs" = {
|
||||
"method" = "GET",
|
||||
"uri" = "${azurerm_key_vault_secret.flag.id}?api-version=7.2",
|
||||
"authentication" = {
|
||||
"type" = "ManagedServiceIdentity",
|
||||
"audience": "https://vault.azure.net"
|
||||
}
|
||||
},
|
||||
"runAfter" = {}
|
||||
},
|
||||
"Response" = {
|
||||
"type" = "Response",
|
||||
"inputs" = {
|
||||
"body" = {
|
||||
"flag" = "@body('GetFlag').value"
|
||||
},
|
||||
"statusCode" = 200
|
||||
},
|
||||
"runAfter" = {
|
||||
"GetFlag" = ["Succeeded"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"triggers" = {
|
||||
"manual" = {
|
||||
"type" = "Request",
|
||||
"kind" = "Http",
|
||||
"inputs" = {
|
||||
"schema" = {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"outputs" = {}
|
||||
},
|
||||
"state" = "Enabled"
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
# provide admin permissions to the key vault for the terraform deployment user, which should be azure admin
|
||||
resource "azurerm_role_assignment" "kv_admin" {
|
||||
principal_id = data.azurerm_client_config.current.object_id
|
||||
role_definition_name = "Key Vault Administrator"
|
||||
scope = azurerm_key_vault.ctf.id
|
||||
}
|
||||
|
||||
|
||||
|
||||
# get the logic app identity and store in a local file
|
||||
resource "null_resource" "get_logicapp_identity" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
cd "challenges/Image-ination Continuation/data/"
|
||||
az logic workflow show \
|
||||
--name ${local.logicapp_name} \
|
||||
--resource-group ${azurerm_resource_group.imageinationcontinuation.name} \
|
||||
--query "identity.principalId" \
|
||||
--output tsv > logicapp_identity.txt
|
||||
EOT
|
||||
interpreter = ["/bin/bash", "-c"]
|
||||
}
|
||||
|
||||
triggers = {
|
||||
always_run = timestamp()
|
||||
}
|
||||
|
||||
depends_on = [azurerm_resource_group_template_deployment.logicapp_with_flag]
|
||||
}
|
||||
|
||||
data "local_file" "logicapp_identity" {
|
||||
filename = "challenges/Image-ination Continuation/data/logicapp_identity.txt"
|
||||
depends_on = [null_resource.get_logicapp_identity]
|
||||
}
|
||||
|
||||
# provide logic app with permissions to get the flag
|
||||
resource "azurerm_role_assignment" "logicapp_kv_reader" {
|
||||
principal_id = data.local_file.logicapp_identity.content
|
||||
role_definition_name = "Key Vault Secrets User"
|
||||
scope = azurerm_key_vault.ctf.id
|
||||
|
||||
depends_on = [data.local_file.logicapp_identity]
|
||||
}
|
||||
|
||||
# create the logic app
|
||||
resource "azuread_application" "sp_app" {
|
||||
display_name = "ctf-logicapp-access"
|
||||
}
|
||||
|
||||
# create service principal
|
||||
resource "azuread_service_principal" "sp" {
|
||||
client_id = azuread_application.sp_app.client_id
|
||||
}
|
||||
|
||||
# create service principal password
|
||||
resource "azuread_service_principal_password" "sp_secret" {
|
||||
service_principal_id = azuread_service_principal.sp.id
|
||||
end_date = timeadd(timestamp(), "720h")
|
||||
|
||||
lifecycle {
|
||||
create_before_destroy = true
|
||||
}
|
||||
}
|
||||
|
||||
# give service principal Reader permissions in the environment
|
||||
resource "azurerm_role_assignment" "sp_reader" {
|
||||
principal_id = azuread_service_principal.sp.object_id
|
||||
role_definition_name = "Reader"
|
||||
scope = "/subscriptions/${data.azurerm_client_config.current.subscription_id}"
|
||||
}
|
||||
|
||||
# Give service principal logic app contributor permissions
|
||||
resource "azurerm_role_assignment" "logicapp_reader" {
|
||||
principal_id = azuread_service_principal.sp.object_id
|
||||
role_definition_name = "Logic App Contributor"
|
||||
scope = "/subscriptions/${data.azurerm_client_config.current.subscription_id}/resourceGroups/${azurerm_resource_group.imageinationcontinuation.name}/providers/Microsoft.Logic/workflows/flag-logicapp-${random_id.suffix.hex}"
|
||||
|
||||
depends_on = [azurerm_resource_group_template_deployment.logicapp_with_flag]
|
||||
}
|
||||
|
||||
# generate local file with service principal credentials, which get stored in the container image from the image-ination station challenge
|
||||
resource "null_resource" "generate_sp_creds" {
|
||||
triggers = {
|
||||
password_version = azuread_service_principal_password.sp_secret.key_id
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
echo '{
|
||||
"client_id": "${azuread_application.sp_app.client_id}",
|
||||
"client_secret": "${azuread_service_principal_password.sp_secret.value}",
|
||||
"tenant_id": "${data.azurerm_client_config.current.tenant_id}",
|
||||
"subscription_id": "${data.azurerm_client_config.current.subscription_id}",
|
||||
"resource": "https://management.azure.com/",
|
||||
"resource_group": "${azurerm_resource_group.imageinationcontinuation.name}"
|
||||
}' > challenges/Image-ination\ Station/data/sp-creds.json
|
||||
EOT
|
||||
}
|
||||
}
|
||||
|
||||
output "some_output" {
|
||||
value = azuread_service_principal_password.sp_secret.key_id
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
variable "azure_region" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_upn" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_object_id" {
|
||||
type = string
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
FROM alpine:latest
|
||||
RUN adduser -D alice
|
||||
RUN mkdir -p /home/alice && echo "FLAG{imageinationStation:interestingStuffCanBeHiddenInImageFiles}" > /home/alice/flag.txt && chown -R alice:alice /home/alice
|
||||
COPY sp-creds.json /tmp/sp-creds.json
|
||||
RUN cat /tmp/sp-creds.json >> /home/alice/logic_app_creds.json
|
||||
RUN apk add --no-cache bash coreutils curl wget iputils busybox-extras procps
|
||||
CMD ["/bin/bash"]
|
||||
@@ -0,0 +1,50 @@
|
||||
# resource group
|
||||
resource "azurerm_resource_group" "imageinationstation" {
|
||||
name = "imageinationstationRG"
|
||||
location = var.azure_region
|
||||
}
|
||||
|
||||
resource "random_id" "suffix" {
|
||||
byte_length = 4
|
||||
}
|
||||
|
||||
# create container registry
|
||||
resource "azurerm_container_registry" "acr" {
|
||||
name = "myacr${random_id.suffix.hex}"
|
||||
resource_group_name = azurerm_resource_group.imageinationstation.name
|
||||
location = azurerm_resource_group.imageinationstation.location
|
||||
sku = "Basic"
|
||||
admin_enabled = true
|
||||
}
|
||||
|
||||
# push image from data folder to container registry
|
||||
resource "null_resource" "docker_push" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
cd "challenges/Image-ination Station/data"
|
||||
docker build -t ${azurerm_container_registry.acr.login_server}/my-app:latest .
|
||||
docker login ${azurerm_container_registry.acr.login_server} -u ${azurerm_container_registry.acr.admin_username} -p ${azurerm_container_registry.acr.admin_password}
|
||||
docker push ${azurerm_container_registry.acr.login_server}/my-app:latest
|
||||
EOT
|
||||
interpreter = ["/bin/sh", "-c"]
|
||||
}
|
||||
|
||||
depends_on = [azurerm_container_registry.acr]
|
||||
triggers = {
|
||||
output = var.depends_on_output
|
||||
}
|
||||
}
|
||||
|
||||
# provide ctf player with pull permissions
|
||||
resource "azurerm_role_assignment" "acr_pull_access" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "AcrPull"
|
||||
scope = azurerm_container_registry.acr.id
|
||||
}
|
||||
|
||||
# provide ctf player with permissions to read container registry
|
||||
resource "azurerm_role_assignment" "acr_read_access" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Reader"
|
||||
scope = azurerm_container_registry.acr.id
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
variable "azure_region" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "depends_on_output" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_upn" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_object_id" {
|
||||
type = string
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
Cinderella is a kind young woman who is mistreated by her stepmother and stepsisters. With the help of her fairy godmother, she attends a royal ball where she captivates the prince. She must leave before midnight, losing a glass slipper in her haste. The prince searches the kingdom for the slipper's owner, and eventually finds Cinderella, whom he marries, leading to a happily ever after.
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
Company Name,Contact Name,Phone Number,Account Number
|
||||
"Moore, Williams and Howard",Jeffrey Buck,001-329-531-9933x811,ACC9152546
|
||||
Lamb LLC,Mariah Taylor,(688)284-2321,ACC7853737
|
||||
Cooper Ltd,Kaitlyn Hall,969-290-4235x36588,ACC4666894
|
||||
Moore-Chung,Johnathan Brown,(160)022-9849x921,ACC6428594
|
||||
"Holmes, Cook and Nixon",Daniel Leonard,+1-142-448-4462x1756,ACC6443104
|
||||
Hernandez PLC,Ronnie Miller,275.701.5101,ACC3956160
|
||||
"Knox, Mcbride and Garcia",Jose Roberts,001-584-829-8325,ACC3381547
|
||||
Vargas-Miller,Allen Fowler,496-091-4830x821,ACC1338965
|
||||
Sutton-Giles,Ms. Susan Mclaughlin MD,743-785-7819,ACC8305704
|
||||
"Rogers, Goodman and Walker",Nicole Lewis,919-646-3100x86195,ACC1351042
|
||||
Russo-Jackson,Brandy Bowen,+1-486-787-3249x1474,ACC8364973
|
||||
Johnson LLC,Dana Taylor,759.028.9938,ACC1059913
|
||||
King-Perez,David Aguilar,(272)705-1445,ACC3569283
|
||||
Hamilton PLC,James Walsh,(672)140-8866,ACC9003263
|
||||
"Stein, Mann and Hicks",Jason Alvarez,001-604-568-2923x04241,ACC5671035
|
||||
Burton-Freeman,Francisco Barnett,(649)166-9393,ACC6599375
|
||||
Petersen-Khan,Toni Waller,+1-433-248-9279x5276,ACC6968903
|
||||
Lewis-Beard,Shirley Davis,3960557191,ACC8168304
|
||||
"Thomas, Coleman and Sparks",Christopher Bailey,+1-444-237-3667x3736,ACC7435431
|
||||
Singh LLC,Christopher White,341.198.4207x1101,ACC3963195
|
||||
Pham Inc,Tracy Farmer,(076)208-5346x5097,ACC1046678
|
||||
"Hernandez, Morrison and Duncan",Dominique Huang,686-944-1314x67632,ACC3957320
|
||||
Gilbert-Meyer,Derek Curry,475.931.1530x4987,ACC5986477
|
||||
Fleming PLC,Daniel Hughes MD,639.490.9675,ACC6509178
|
||||
Aguirre-Frey,Michael Singh,(691)077-4246x1917,ACC4565589
|
||||
"Hurley, Rodriguez and Rodriguez",Morgan Sanders,077-522-1436x3793,ACC8308658
|
||||
"Lee, Patel and Nelson",Dennis Melendez,+1-238-174-3567x551,ACC9522388
|
||||
Medina-Burns,Meghan Sanders,(201)220-6129,ACC5453422
|
||||
Floyd and Sons,Curtis Mccarthy,(204)365-8350x65420,ACC3920241
|
||||
Duran Inc,Jasmine Stephens,988-261-9650x97646,ACC9777507
|
||||
"Brown, West and Lane",Daniel Hamilton,(836)570-0594,ACC1611446
|
||||
"Gonzalez, Hoffman and Walker",Denise Smith,723-231-9986x02347,ACC5409826
|
||||
Allen LLC,Matthew Wallace,416-688-9957x1041,ACC5244411
|
||||
Holder Group,Andrea Hicks,708.401.2880x3317,ACC9684757
|
||||
Burns-Harris,Gregory Garner,8717086592,ACC3243985
|
||||
Burns and Sons,Christine Hill,600.992.7003,ACC5939428
|
||||
Martin Group,Michelle Davis,875.132.3763x04584,ACC6236484
|
||||
Baker-Campbell,Ralph Decker,+1-071-070-0191x208,ACC4704261
|
||||
"Henry, Vasquez and Blackwell",Kim Fuller,092.916.9672,ACC7815217
|
||||
"Owens, Taylor and Morgan",Lisa Roth,0408349918,ACC8013568
|
||||
"Griffith, Weaver and Payne",Richard Boone,001-811-295-5742x71145,ACC3869952
|
||||
"Jones, Harris and Figueroa",Chelsea Mcdaniel,001-817-091-0223,ACC1097157
|
||||
"Garcia, Trujillo and Carpenter",Wendy Bailey,1319801073,ACC2095110
|
||||
White Ltd,Brian Cole,846-143-0853,ACC1078744
|
||||
Flores Inc,Madison Strickland,+1-211-796-4471,ACC5288837
|
||||
"Tucker, Valencia and Rivera",Jaime Clark,471-220-0871x85925,ACC4047815
|
||||
"Rodriguez, Vega and Bishop",Melanie Reynolds,(641)602-7556,ACC7848165
|
||||
Goodwin-Colon,Nancy Richardson,720-800-1277x6554,ACC5134045
|
||||
Rodriguez Ltd,Jennifer Williams,(578)134-1303x31096,ACC0861327
|
||||
Brown and Sons,Jerry Woods,108-257-6297x4167,ACC0403570
|
||||
|
@@ -0,0 +1 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
Firstname,Lastname,email,Hiredate
|
||||
Madeline,Gibson,[email protected],2023-11-21
|
||||
Cody,Thompson,[email protected],2022-02-24
|
||||
Jeremy,Barton,[email protected],2021-02-07
|
||||
Sheri,Mcknight,[email protected],2022-12-11
|
||||
Jessica,Ray,[email protected],2023-05-15
|
||||
Kevin,Wells,[email protected],2024-04-27
|
||||
Michael,Harris,[email protected],2022-08-24
|
||||
Sandra,Pierce,[email protected],2023-08-12
|
||||
Veronica,Arnold,[email protected],2022-07-26
|
||||
Sharon,Gomez,[email protected],2023-04-10
|
||||
Grace,Wong,[email protected],2020-04-24
|
||||
Kim,Estrada,[email protected],2023-05-22
|
||||
Laura,Clayton,[email protected],2021-06-27
|
||||
Paul,Robinson,[email protected],2021-12-12
|
||||
Matthew,Smith,[email protected],2022-05-08
|
||||
Anita,Cruz,[email protected],2022-01-09
|
||||
Tyler,Turner,[email protected],2021-12-08
|
||||
David,Branch,[email protected],2021-11-16
|
||||
Gregory,Ayala,[email protected],2022-02-28
|
||||
Alexander,Jensen,[email protected],2021-03-12
|
||||
Cheryl,Payne,[email protected],2022-02-13
|
||||
Marie,Hood,[email protected],2023-06-12
|
||||
Michael,Yang,[email protected],2021-08-06
|
||||
Tiffany,Jordan,[email protected],2024-12-27
|
||||
Michelle,Brown,[email protected],2022-05-03
|
||||
Allison,Alvarado,[email protected],2024-05-17
|
||||
Janet,Freeman,[email protected],2023-12-19
|
||||
Jason,Mclaughlin,[email protected],2024-10-17
|
||||
Scott,Garcia,[email protected],2022-12-13
|
||||
Sean,Moreno,[email protected],2022-12-16
|
||||
Matthew,Smith,[email protected],2021-09-14
|
||||
Jasmine,Anderson,[email protected],2021-10-15
|
||||
Ryan,Campbell,[email protected],2024-10-19
|
||||
Lisa,Patterson,[email protected],2024-09-30
|
||||
Scott,Hardy,[email protected],2020-07-25
|
||||
Gregory,Johnson,[email protected],2020-05-01
|
||||
Scott,Collins,[email protected],2021-02-22
|
||||
Amanda,Hall,[email protected],2022-05-06
|
||||
Mary,Russell,[email protected],2021-08-13
|
||||
Devon,Becker,[email protected],2022-09-19
|
||||
Jorge,Lutz,[email protected],2020-04-29
|
||||
Gabriel,Jones,[email protected],2023-07-14
|
||||
Gary,Waters,[email protected],2022-02-28
|
||||
Amy,Zavala,[email protected],2021-05-31
|
||||
Michael,Solis,[email protected],2021-11-19
|
||||
Kenneth,Trujillo,[email protected],2022-07-20
|
||||
Suzanne,Marsh,[email protected],2020-08-02
|
||||
Bryan,Peters,[email protected],2024-12-28
|
||||
Patricia,Oneal,[email protected],2022-02-04
|
||||
Anita,Brown,[email protected],2021-02-14
|
||||
|
@@ -0,0 +1 @@
|
||||
FLAG{notsosecret:shouldThisStorageBlobBePubliclyAccessible}
|
||||
@@ -0,0 +1 @@
|
||||
Jack, a poor boy, trades his family's cow for magic beans. The beans grow into a giant beanstalk that reaches the sky. Jack climbs it and discovers a giant's castle filled with treasures. He steals from the giant and escapes, eventually chopping down the beanstalk and killing the pursuing giant. Jack and his mother live happily ever after with the riches.
|
||||
@@ -0,0 +1 @@
|
||||
Little Red Riding Hood is a young girl who visits her grandmother's house, unaware that a cunning wolf has taken her grandmother's place. The wolf deceives her and tries to eat her, but depending on the version, a huntsman or woodsman rescues her and her grandmother in time. The tale teaches the importance of caution and not talking to strangers.
|
||||
+1
@@ -0,0 +1 @@
|
||||
Snow White is a beautiful princess hated by her jealous stepmother, the queen. The queen tries to kill her multiple times, but Snow White is protected by seven dwarfs. Eventually, she is poisoned by a magical apple. A prince finds her in a glass coffin, awakens her with a kiss, and marries her. The evil queen meets a grim fate, and Snow White lives happily ever after.
|
||||
@@ -0,0 +1,209 @@
|
||||
# resource group
|
||||
resource "azurerm_resource_group" "notsosecret" {
|
||||
name = "notsosecretRG"
|
||||
location = var.azure_region
|
||||
}
|
||||
|
||||
resource "random_id" "suffix" {
|
||||
byte_length = 5
|
||||
}
|
||||
|
||||
resource "random_id" "suffix2" {
|
||||
byte_length = 5
|
||||
}
|
||||
|
||||
# RBAC Permissions
|
||||
resource "azurerm_role_assignment" "storage_blob_reader" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Storage Blob Data Reader"
|
||||
scope = azurerm_storage_account.storage_account_1.id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "reader" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Reader"
|
||||
scope = azurerm_storage_account.storage_account_1.id
|
||||
}
|
||||
|
||||
# create storage account 1
|
||||
resource "azurerm_storage_account" "storage_account_1" {
|
||||
name = "notsosecret${random_id.suffix.hex}"
|
||||
resource_group_name = azurerm_resource_group.notsosecret.name
|
||||
location = azurerm_resource_group.notsosecret.location
|
||||
account_tier = "Standard"
|
||||
account_replication_type = "LRS"
|
||||
}
|
||||
|
||||
# create storage account 2
|
||||
resource "azurerm_storage_account" "storage_account_2" {
|
||||
name = "notsosecret${random_id.suffix2.hex}"
|
||||
resource_group_name = azurerm_resource_group.notsosecret.name
|
||||
location = azurerm_resource_group.notsosecret.location
|
||||
account_tier = "Standard"
|
||||
account_replication_type = "LRS"
|
||||
allow_nested_items_to_be_public = true
|
||||
}
|
||||
|
||||
# create container 1 in storage account 1
|
||||
resource "azurerm_storage_container" "storage_container_1" {
|
||||
name = "files"
|
||||
storage_account_id = azurerm_storage_account.storage_account_1.id
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
# create file 1 in container
|
||||
resource "azurerm_storage_blob" "file1" {
|
||||
name = "cinderella.txt"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/cinderella.txt"
|
||||
storage_account_name = azurerm_storage_account.storage_account_1.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_1.name
|
||||
content_type = "text/plain"
|
||||
}
|
||||
|
||||
# create file 2 in container
|
||||
resource "azurerm_storage_blob" "file2" {
|
||||
name = "jack_and_the_beanstalk.txt"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/jack_and_the_beanstalk.txt"
|
||||
storage_account_name = azurerm_storage_account.storage_account_1.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_1.name
|
||||
content_type = "text/plain"
|
||||
}
|
||||
|
||||
# create file 3 in container
|
||||
resource "azurerm_storage_blob" "file3" {
|
||||
name = "little_red_riding_hood.txt"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/little_red_riding_hood.txt"
|
||||
storage_account_name = azurerm_storage_account.storage_account_1.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_1.name
|
||||
content_type = "text/plain"
|
||||
}
|
||||
|
||||
# create file 4 in container
|
||||
resource "azurerm_storage_blob" "file4" {
|
||||
name = "snow_white.txt"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/snow_white.txt"
|
||||
storage_account_name = azurerm_storage_account.storage_account_1.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_1.name
|
||||
content_type = "text/plain"
|
||||
}
|
||||
|
||||
# create container 2 in storage account 1
|
||||
resource "azurerm_storage_container" "storage_container_2" {
|
||||
name = "contacts"
|
||||
storage_account_id = azurerm_storage_account.storage_account_1.id
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
# create file 5 in container 2
|
||||
|
||||
resource "azurerm_storage_blob" "file5" {
|
||||
name = "contacts.csv"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/contacts.csv"
|
||||
storage_account_name = azurerm_storage_account.storage_account_1.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_2.name
|
||||
content_type = "text/csv"
|
||||
}
|
||||
|
||||
# create container 3 in storage account 1
|
||||
resource "azurerm_storage_container" "storage_container_3" {
|
||||
name = "policies"
|
||||
storage_account_id = azurerm_storage_account.storage_account_1.id
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
# create file 6 in container 3
|
||||
resource "azurerm_storage_blob" "file6" {
|
||||
name = "employeePolicy.txt"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/employeePolicy.txt"
|
||||
storage_account_name = azurerm_storage_account.storage_account_1.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_3.name
|
||||
content_type = "text/plain"
|
||||
}
|
||||
|
||||
# create container 4 in storage account 1
|
||||
resource "azurerm_storage_container" "storage_container_4" {
|
||||
name = "employees"
|
||||
storage_account_id = azurerm_storage_account.storage_account_1.id
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
# create file 7 in container 4
|
||||
resource "azurerm_storage_blob" "file7" {
|
||||
name = "employees.csv"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/employees.csv"
|
||||
storage_account_name = azurerm_storage_account.storage_account_1.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_4.name
|
||||
content_type = "text/csv"
|
||||
}
|
||||
|
||||
# create container 5 in storage account 1
|
||||
resource "azurerm_storage_container" "storage_container_5" {
|
||||
name = "assets"
|
||||
storage_account_id = azurerm_storage_account.storage_account_1.id
|
||||
container_access_type = "private"
|
||||
}
|
||||
|
||||
# create local file with data
|
||||
resource "local_file" "assets_csv" {
|
||||
content = <<EOT
|
||||
Asset,Type,Details
|
||||
prodDB1,Database,Production Database containing employees
|
||||
prodDB2,Database,Production Database containing contacts
|
||||
prodDB3,Database,Production Database containing HR data
|
||||
prodDB4,Database,Production Database containing assets
|
||||
adminVM,Virtual Machine,VM for admin functionality
|
||||
devVM,Virtual Machine,VM for developer use
|
||||
jumpbox,Virtual Machine,Jumpbox to access private network
|
||||
prodLB1,Load Balancer,Production load balancer East
|
||||
prodLB2,Load Balancer,Production load balancer West
|
||||
stageLB1,Load Balancer,Stage load balancer East
|
||||
stageLB2,Load Balancer,Stage load balancer West
|
||||
internalEast,Virtual Network,Internal network East
|
||||
internalWest,Virtual Network,Internal network West
|
||||
private,Virtual Network,Private network
|
||||
${azurerm_storage_account.storage_account_1.name},Storage Account,Storage account East
|
||||
${azurerm_storage_account.storage_account_2.name},Storage Account,Storage account West
|
||||
files,Container,${azurerm_storage_account.storage_account_1.name}
|
||||
contacts,Container,${azurerm_storage_account.storage_account_1.name}
|
||||
policies,Container,${azurerm_storage_account.storage_account_1.name}
|
||||
employees,Container,${azurerm_storage_account.storage_account_1.name}
|
||||
assets, Container,${azurerm_storage_account.storage_account_1.name}
|
||||
sensitivefiles,Container,${azurerm_storage_account.storage_account_2.name}
|
||||
EOT
|
||||
filename = "challenges/Not so secret/data/assets.csv"
|
||||
}
|
||||
|
||||
# create file 8 in container 5
|
||||
resource "azurerm_storage_blob" "file8" {
|
||||
name = "assets.csv"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/assets.csv"
|
||||
storage_account_name = azurerm_storage_account.storage_account_1.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_5.name
|
||||
content_type = "text/csv"
|
||||
depends_on = [local_file.assets_csv]
|
||||
}
|
||||
|
||||
# create container 6 in storage account 2
|
||||
resource "azurerm_storage_container" "storage_container_6" {
|
||||
name = "sensitivefiles"
|
||||
storage_account_id = azurerm_storage_account.storage_account_2.id
|
||||
container_access_type = "container"
|
||||
}
|
||||
|
||||
# create file 9 (flag) in container 6
|
||||
resource "azurerm_storage_blob" "file9" {
|
||||
name = "flag.txt"
|
||||
type = "Block"
|
||||
source = "challenges/Not so secret/data/flag.txt"
|
||||
storage_account_name = azurerm_storage_account.storage_account_2.name
|
||||
storage_container_name = azurerm_storage_container.storage_container_6.name
|
||||
content_type = "text/plain"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
variable "azure_region" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_upn" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_object_id" {
|
||||
type = string
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
# resource group
|
||||
resource "azurerm_resource_group" "permisery" {
|
||||
name = "permiseryRG"
|
||||
location = var.azure_region
|
||||
}
|
||||
|
||||
resource "random_id" "suffix" {
|
||||
byte_length = 4
|
||||
}
|
||||
|
||||
resource "random_id" "suffix2" {
|
||||
byte_length = 4
|
||||
}
|
||||
|
||||
data "azurerm_client_config" "current" {}
|
||||
|
||||
# get IP needed for IP rules when creating key vault
|
||||
data "http" "current_ip" {
|
||||
url = "https://icanhazip.com"
|
||||
}
|
||||
|
||||
locals {
|
||||
user_ip = chomp(data.http.current_ip.response_body)
|
||||
}
|
||||
|
||||
# create key vault
|
||||
resource "azurerm_key_vault" "ctf" {
|
||||
name = "ctfkv${random_id.suffix.hex}"
|
||||
resource_group_name = azurerm_resource_group.permisery.name
|
||||
location = azurerm_resource_group.permisery.location
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
sku_name = "standard"
|
||||
purge_protection_enabled = false
|
||||
soft_delete_retention_days = 7
|
||||
enable_rbac_authorization = true
|
||||
|
||||
network_acls {
|
||||
default_action = "Deny"
|
||||
bypass = "AzureServices"
|
||||
ip_rules = concat(split(",", azurerm_linux_web_app.webapp.possible_outbound_ip_addresses), [local.user_ip])
|
||||
}
|
||||
|
||||
depends_on = [azurerm_linux_web_app.webapp]
|
||||
}
|
||||
|
||||
# put a flag in the key vault
|
||||
resource "azurerm_key_vault_secret" "flag" {
|
||||
name = "flag"
|
||||
value = "FLAG{permisery:SSRFInTheCloudIsAlwaysFun}"
|
||||
key_vault_id = azurerm_key_vault.ctf.id
|
||||
depends_on = [azurerm_role_assignment.kv_admin]
|
||||
}
|
||||
|
||||
# provide admin rights to user under which terraform is running (should be azure admin user)
|
||||
resource "azurerm_role_assignment" "kv_admin" {
|
||||
principal_id = data.azurerm_client_config.current.object_id
|
||||
role_definition_name = "Key Vault Administrator"
|
||||
scope = azurerm_key_vault.ctf.id
|
||||
}
|
||||
|
||||
# provide reader permissions to ctf player
|
||||
resource "azurerm_role_assignment" "guest_kv_reader" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Key Vault Reader"
|
||||
scope = azurerm_key_vault.ctf.id
|
||||
}
|
||||
|
||||
# create a service plan (free tier), needed to create the web app
|
||||
resource "azurerm_service_plan" "cloudfoxable" {
|
||||
name = "cloudfoxable"
|
||||
resource_group_name = azurerm_resource_group.permisery.name
|
||||
location = azurerm_resource_group.permisery.location
|
||||
os_type = "Linux"
|
||||
sku_name = "F1"
|
||||
}
|
||||
|
||||
# create web app
|
||||
resource "azurerm_linux_web_app" "webapp" {
|
||||
name = "myfirstwebapp-${random_id.suffix2.hex}"
|
||||
resource_group_name = azurerm_resource_group.permisery.name
|
||||
location = azurerm_resource_group.permisery.location
|
||||
service_plan_id = azurerm_service_plan.cloudfoxable.id
|
||||
|
||||
identity {
|
||||
type = "SystemAssigned"
|
||||
}
|
||||
|
||||
site_config {
|
||||
application_stack {
|
||||
python_version = "3.9"
|
||||
}
|
||||
always_on = false
|
||||
}
|
||||
|
||||
app_settings = {
|
||||
WEBSITES_ENABLE_APP_SERVICE_STORAGE = "false"
|
||||
SCM_DO_BUILD_DURING_DEPLOYMENT = "true"
|
||||
ENABLE_ORYX_BUILD = "true"
|
||||
}
|
||||
|
||||
depends_on = [azurerm_service_plan.cloudfoxable]
|
||||
}
|
||||
|
||||
# give ctf player reader permissions
|
||||
resource "azurerm_role_assignment" "webapp_reader" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Reader"
|
||||
scope = azurerm_linux_web_app.webapp.id
|
||||
}
|
||||
|
||||
# give the web app permission to read the key vault secrets
|
||||
resource "azurerm_role_assignment" "webapp_secret_reader" {
|
||||
principal_id = azurerm_linux_web_app.webapp.identity[0].principal_id
|
||||
role_definition_name = "Key Vault Secrets User"
|
||||
scope = azurerm_key_vault.ctf.id
|
||||
}
|
||||
|
||||
# defintion of the program running on the web app
|
||||
resource "local_file" "app_py" {
|
||||
filename = "challenges/Permisery/data/app.py"
|
||||
content = <<EOT
|
||||
from flask import (Flask, request, render_template_string)
|
||||
import requests
|
||||
import os
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
form_template = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title>Test Site</title></head>
|
||||
<body>
|
||||
<p>Hello World! This is just a test site to generate web requests. Enter the target URL below. Custom headers can be included if needed.</p>
|
||||
<p>Additionally, for testing purposes the system environment variables can be found <a href="/env">here</a>.
|
||||
<form method="POST">
|
||||
<label>Target URL:</label><br>
|
||||
<input type="text" name="url" size="50"><br><br>
|
||||
|
||||
<label>Custom Header 1:</label><br>
|
||||
Key: <input type="text" name="header1_key">
|
||||
Value: <input type="text" name="header1_value"><br><br>
|
||||
|
||||
<label>Custom Header 2:</label><br>
|
||||
Key: <input type="text" name="header2_key">
|
||||
Value: <input type="text" name="header2_value"><br><br>
|
||||
|
||||
<label>Custom Header 3:</label><br>
|
||||
Key: <input type="text" name="header3_key">
|
||||
Value: <input type="text" name="header3_value"><br><br>
|
||||
|
||||
<input type="submit" value="Fetch">
|
||||
</form>
|
||||
|
||||
{% if result %}
|
||||
<hr>
|
||||
<h3>Response from {{ url }}:</h3>
|
||||
<strong>Status:</strong> {{ status }}<br><br>
|
||||
<pre>{{ result }}</pre>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
@app.route("/", methods=["GET", "POST"])
|
||||
def index():
|
||||
result = status = url = None
|
||||
|
||||
if request.method == "POST":
|
||||
url = request.form.get("url")
|
||||
headers = {}
|
||||
|
||||
for i in range(1, 4):
|
||||
key = request.form.get(f"header{i}_key")
|
||||
value = request.form.get(f"header{i}_value")
|
||||
if key and value:
|
||||
headers[key] = value
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers, timeout=3)
|
||||
status = response.status_code
|
||||
result = response.text
|
||||
except Exception as e:
|
||||
status = "Error"
|
||||
result = str(e)
|
||||
|
||||
return render_template_string(form_template, result=result, status=status, url=url)
|
||||
|
||||
@app.route("/env")
|
||||
def show_env():
|
||||
env_vars = dict(os.environ)
|
||||
formatted = "<h2>Environment Variables</h2><pre>{}</pre>".format(
|
||||
"\n".join(f"{k}={v}" for k, v in sorted(env_vars.items()))
|
||||
)
|
||||
return formatted
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
||||
EOT
|
||||
}
|
||||
|
||||
# requirements.txt
|
||||
resource "local_file" "requirements_txt" {
|
||||
filename = "challenges/Permisery/data/requirements.txt"
|
||||
content = <<EOT
|
||||
flask
|
||||
gunicorn
|
||||
requests
|
||||
EOT
|
||||
}
|
||||
|
||||
# zip everything up
|
||||
data "archive_file" "app_zip" {
|
||||
type = "zip"
|
||||
source_dir = "challenges/Permisery/data/"
|
||||
output_path = "challenges/Permisery/zip/app.zip"
|
||||
|
||||
depends_on = [resource.local_file.requirements_txt, resource.local_file.app_py]
|
||||
}
|
||||
|
||||
# deploy the zip to the webapp
|
||||
resource "null_resource" "zip_deploy" {
|
||||
provisioner "local-exec" {
|
||||
command = <<EOT
|
||||
az webapp deploy --resource-group ${azurerm_resource_group.permisery.name} \
|
||||
--name ${azurerm_linux_web_app.webapp.name} \
|
||||
--src-path ${data.archive_file.app_zip.output_path} \
|
||||
--type zip
|
||||
EOT
|
||||
}
|
||||
|
||||
depends_on = [azurerm_linux_web_app.webapp, data.archive_file.app_zip]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
variable "azure_region" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_upn" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_object_id" {
|
||||
type = string
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#cloud-config
|
||||
ssh_pwauth: true
|
||||
|
||||
users:
|
||||
- default
|
||||
- name: bob
|
||||
groups: [sudo]
|
||||
shell: /bin/bash
|
||||
sudo: "ALL=(ALL) NOPASSWD:ALL"
|
||||
lock_passwd: true
|
||||
|
||||
write_files:
|
||||
- path: /home/bob/personalnotes.txt
|
||||
owner: root:root
|
||||
permissions: '0640'
|
||||
content: |
|
||||
Personal Notes (do not share)
|
||||
|
||||
Shopping list:
|
||||
- coffee beans
|
||||
- eggs
|
||||
- tortillas
|
||||
- pasta
|
||||
- canned tomatoes
|
||||
- laundry detergent
|
||||
- cat litter
|
||||
|
||||
Birthdays / reminders:
|
||||
- Mom: May 12
|
||||
- Alex: Aug 3
|
||||
- Dentist: Apr 18 @ 10:30am
|
||||
- Car registration due: Sept 30
|
||||
|
||||
Random stuff:
|
||||
- Remember to cancel the trial subscription before Friday.
|
||||
- Replace batteries in the smoke detector.
|
||||
- Check storage closet for the spare HDMI cable.
|
||||
|
||||
------------------------------------------------------------
|
||||
Personal project notes:
|
||||
- Key Vault name: ${keyvault_name}
|
||||
- Secret name: ctf-flag
|
||||
|
||||
runcmd:
|
||||
- [ bash, -lc, "mkdir -p /home/bob && chown -R bob:bob /home/bob && chmod 750 /home/bob && chown bob:bob /home/bob/personalnotes.txt" ]
|
||||
@@ -0,0 +1,11 @@
|
||||
variable "azure_region" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_upn" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "player_object_id" {
|
||||
type = string
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
# resource group
|
||||
resource "azurerm_resource_group" "vmiam" {
|
||||
name = "vmiamRG"
|
||||
location = var.azure_region
|
||||
}
|
||||
|
||||
data "azurerm_client_config" "current" {}
|
||||
|
||||
resource "random_string" "rand" {
|
||||
length = 6
|
||||
upper = false
|
||||
numeric = true
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "random_id" "suffix" {
|
||||
byte_length = 4
|
||||
}
|
||||
|
||||
data "http" "current_ip" {
|
||||
url = "https://icanhazip.com"
|
||||
}
|
||||
|
||||
locals {
|
||||
user_ip = chomp(data.http.current_ip.response_body)
|
||||
}
|
||||
|
||||
# Key Vault
|
||||
resource "azurerm_key_vault" "ctf_kv" {
|
||||
name = "ctfkv${random_string.rand.id}"
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
location = azurerm_resource_group.vmiam.location
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
sku_name = "standard"
|
||||
purge_protection_enabled = false
|
||||
enable_rbac_authorization = true
|
||||
}
|
||||
|
||||
# Create secret
|
||||
resource "azurerm_role_assignment" "terraform_admin_rbac" {
|
||||
principal_id = data.azurerm_client_config.current.object_id
|
||||
role_definition_name = "Key Vault Administrator"
|
||||
scope = azurerm_key_vault.ctf_kv.id
|
||||
}
|
||||
|
||||
# Secret(flag)
|
||||
resource "azurerm_key_vault_secret" "flag" {
|
||||
name = "ctf-flag"
|
||||
value = "FLAG{vmIAm:keyvaultMisconfiguredRead}"
|
||||
key_vault_id = azurerm_key_vault.ctf_kv.id
|
||||
|
||||
depends_on = [
|
||||
azurerm_role_assignment.terraform_admin_rbac
|
||||
]
|
||||
}
|
||||
|
||||
# Managed Identity
|
||||
resource "azurerm_user_assigned_identity" "ctf_identity" {
|
||||
name = "ctf-kv-reader-id"
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
location = azurerm_resource_group.vmiam.location
|
||||
}
|
||||
|
||||
# RBAC
|
||||
resource "azurerm_role_assignment" "kv_reader" {
|
||||
principal_id = azurerm_user_assigned_identity.ctf_identity.principal_id
|
||||
role_definition_name = "Key Vault Secrets User"
|
||||
scope = azurerm_key_vault.ctf_kv.id
|
||||
}
|
||||
|
||||
# VM Network
|
||||
resource "azurerm_virtual_network" "ctf_vnet" {
|
||||
name = "ctf-vnet"
|
||||
address_space = ["10.0.0.0/16"]
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
location = azurerm_resource_group.vmiam.location
|
||||
}
|
||||
|
||||
resource "azurerm_subnet" "ctf_subnet" {
|
||||
name = "ctf-subnet"
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
virtual_network_name = azurerm_virtual_network.ctf_vnet.name
|
||||
address_prefixes = ["10.0.1.0/24"]
|
||||
}
|
||||
|
||||
resource "azurerm_public_ip" "ctf_ip" {
|
||||
name = "ctf-public-ip"
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
location = azurerm_resource_group.vmiam.location
|
||||
allocation_method = "Static"
|
||||
}
|
||||
|
||||
# let user discover the IP
|
||||
resource "azurerm_role_assignment" "player_ip_reader" {
|
||||
scope = azurerm_public_ip.ctf_ip.id
|
||||
role_definition_name = "Reader"
|
||||
principal_id = var.player_object_id
|
||||
}
|
||||
|
||||
resource "azurerm_network_interface" "ctf_nic" {
|
||||
name = "ctf-nic"
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
location = azurerm_resource_group.vmiam.location
|
||||
|
||||
ip_configuration {
|
||||
name = "internal"
|
||||
subnet_id = azurerm_subnet.ctf_subnet.id
|
||||
private_ip_address_allocation = "Static"
|
||||
private_ip_address = "10.0.1.4"
|
||||
public_ip_address_id = azurerm_public_ip.ctf_ip.id
|
||||
}
|
||||
}
|
||||
|
||||
# let user discover the nic
|
||||
resource "azurerm_role_assignment" "player_nic_reader" {
|
||||
scope = azurerm_network_interface.ctf_nic.id
|
||||
role_definition_name = "Reader"
|
||||
principal_id = var.player_object_id
|
||||
}
|
||||
|
||||
resource "azurerm_network_security_group" "ctf_nsg" {
|
||||
name = "ctf-nsg"
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
location = azurerm_resource_group.vmiam.location
|
||||
|
||||
security_rule {
|
||||
name = "Allow-SSH"
|
||||
priority = 1001
|
||||
direction = "Inbound"
|
||||
access = "Allow"
|
||||
protocol = "Tcp"
|
||||
source_port_range = "*"
|
||||
destination_port_range = "22"
|
||||
source_address_prefix = local.user_ip
|
||||
destination_address_prefix = "*"
|
||||
}
|
||||
}
|
||||
|
||||
resource "azurerm_subnet_network_security_group_association" "ctf_subnet_assoc" {
|
||||
subnet_id = azurerm_subnet.ctf_subnet.id
|
||||
network_security_group_id = azurerm_network_security_group.ctf_nsg.id
|
||||
}
|
||||
|
||||
# VM
|
||||
resource "azurerm_linux_virtual_machine" "ctf_vm" {
|
||||
name = "ctf-vm"
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
location = azurerm_resource_group.vmiam.location
|
||||
size = "Standard_B1s"
|
||||
admin_username = "azureuser"
|
||||
disable_password_authentication = false
|
||||
admin_password = "P@ssword1234!"
|
||||
|
||||
network_interface_ids = [
|
||||
azurerm_network_interface.ctf_nic.id
|
||||
]
|
||||
|
||||
os_disk {
|
||||
caching = "ReadWrite"
|
||||
storage_account_type = "Standard_LRS"
|
||||
}
|
||||
|
||||
source_image_reference {
|
||||
publisher = "Canonical"
|
||||
offer = "0001-com-ubuntu-server-focal"
|
||||
sku = "20_04-lts"
|
||||
version = "latest"
|
||||
}
|
||||
|
||||
identity {
|
||||
type = "UserAssigned"
|
||||
identity_ids = [azurerm_user_assigned_identity.ctf_identity.id]
|
||||
}
|
||||
|
||||
custom_data = base64encode(templatefile("${path.module}/data/cloud-init.yaml.tftpl", {
|
||||
keyvault_name = azurerm_key_vault.ctf_kv.name
|
||||
}))
|
||||
|
||||
depends_on = [
|
||||
azurerm_key_vault.ctf_kv
|
||||
]
|
||||
}
|
||||
|
||||
# let user discover the vm
|
||||
resource "azurerm_role_assignment" "player_vm_reader" {
|
||||
scope = azurerm_linux_virtual_machine.ctf_vm.id
|
||||
role_definition_name = "Reader"
|
||||
principal_id = var.player_object_id
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault" "ctf2" {
|
||||
name = "ctfkv${random_id.suffix.hex}"
|
||||
resource_group_name = azurerm_resource_group.vmiam.name
|
||||
location = azurerm_resource_group.vmiam.location
|
||||
tenant_id = data.azurerm_client_config.current.tenant_id
|
||||
sku_name = "standard"
|
||||
purge_protection_enabled = false
|
||||
enable_rbac_authorization = true
|
||||
|
||||
network_acls {
|
||||
default_action = "Deny"
|
||||
bypass = "AzureServices"
|
||||
ip_rules = [local.user_ip]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
resource "azurerm_key_vault_secret" "creds" {
|
||||
name = "creds"
|
||||
value = "azureuser:P@ssword1234!"
|
||||
key_vault_id = azurerm_key_vault.ctf2.id
|
||||
|
||||
depends_on = [
|
||||
azurerm_role_assignment.deploy_kv_admin
|
||||
]
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "kv_reader2" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Reader"
|
||||
scope = azurerm_key_vault.ctf2.id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "kv_secrets_reader" {
|
||||
principal_id = var.player_object_id
|
||||
role_definition_name = "Key Vault Secrets User"
|
||||
scope = azurerm_key_vault.ctf2.id
|
||||
}
|
||||
|
||||
resource "azurerm_role_assignment" "deploy_kv_admin" {
|
||||
principal_id = data.azurerm_client_config.current.object_id
|
||||
role_definition_name = "Key Vault Administrator"
|
||||
scope = azurerm_key_vault.ctf2.id
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
# Configure the Azure provider
|
||||
|
||||
terraform {
|
||||
required_providers {
|
||||
azurerm = {
|
||||
source = "hashicorp/azurerm"
|
||||
version = "~> 4.26.0"
|
||||
}
|
||||
local = {
|
||||
source = "hashicorp/local"
|
||||
version = "~> 2.0"
|
||||
}
|
||||
}
|
||||
|
||||
required_version = ">= 1.3"
|
||||
}
|
||||
|
||||
provider "azurerm" {
|
||||
features {
|
||||
key_vault {
|
||||
recover_soft_deleted_key_vaults = false
|
||||
purge_soft_delete_on_destroy = true
|
||||
}
|
||||
}
|
||||
subscription_id = var.subscription_id
|
||||
}
|
||||
|
||||
data "azurerm_client_config" "current" {}
|
||||
|
||||
# user password
|
||||
resource "random_password" "ctf_user_pw" {
|
||||
length = 14
|
||||
special = true
|
||||
override_special = "!@#$%^&*-_=+"
|
||||
}
|
||||
|
||||
# user account, which will be "willem@<azure-domain>
|
||||
resource "azuread_user" "ctf_user" {
|
||||
display_name = "willem"
|
||||
user_principal_name = "willem${var.domain}"
|
||||
mail_nickname = "willem"
|
||||
password = random_password.ctf_user_pw.result
|
||||
account_enabled = true
|
||||
}
|
||||
|
||||
module "challenge_notsosecret" {
|
||||
count = var.notsosecret_enabled ? 1 : 0
|
||||
source = "./challenges/Not so secret"
|
||||
azure_region = var.azure_region
|
||||
player_upn = azuread_user.ctf_user.user_principal_name
|
||||
player_object_id = azuread_user.ctf_user.object_id
|
||||
}
|
||||
|
||||
module "challenge_permisery" {
|
||||
count = var.permisery_enabled ? 1 : 0
|
||||
source = "./challenges/Permisery"
|
||||
azure_region = var.azure_region
|
||||
player_upn = azuread_user.ctf_user.user_principal_name
|
||||
player_object_id = azuread_user.ctf_user.object_id
|
||||
}
|
||||
|
||||
module "challenge_image-inationcontinuation" {
|
||||
count = var.imageination_enabled ? 1 : 0
|
||||
source = "./challenges/Image-ination Continuation"
|
||||
azure_region = var.azure_region
|
||||
player_upn = azuread_user.ctf_user.user_principal_name
|
||||
player_object_id = azuread_user.ctf_user.object_id
|
||||
}
|
||||
|
||||
module "challenge_image-inationstation" {
|
||||
count = var.imageination_enabled ? 1 : 0
|
||||
source = "./challenges/Image-ination Station"
|
||||
azure_region = var.azure_region
|
||||
player_upn = azuread_user.ctf_user.user_principal_name
|
||||
player_object_id = azuread_user.ctf_user.object_id
|
||||
depends_on = [module.challenge_image-inationcontinuation]
|
||||
depends_on_output = module.challenge_image-inationcontinuation[0].some_output # needed to make sure stuff finishes before other stuff
|
||||
}
|
||||
|
||||
module "challenge_vmiam" {
|
||||
count = var.vmiam_enabled ? 1 : 0
|
||||
source = "./challenges/VM I Am"
|
||||
azure_region = var.azure_region
|
||||
player_upn = azuread_user.ctf_user.user_principal_name
|
||||
player_object_id = azuread_user.ctf_user.object_id
|
||||
}
|
||||
|
||||
module "challenge_cloudjumping" {
|
||||
count = var.cloudjumping_enabled ? 1 : 0
|
||||
source = "./challenges/Cloud Jumping"
|
||||
azure_region = var.azure_region
|
||||
player_upn = azuread_user.ctf_user.user_principal_name
|
||||
player_object_id = azuread_user.ctf_user.object_id
|
||||
}
|
||||
|
||||
locals {
|
||||
challenge_catalog = [
|
||||
{
|
||||
enabled = var.notsosecret_enabled
|
||||
name = "Not So Secret"
|
||||
cost = "~$0.01/month"
|
||||
},
|
||||
{
|
||||
enabled = var.permisery_enabled
|
||||
name = "Permisery"
|
||||
cost = "~$0/month"
|
||||
},
|
||||
{
|
||||
enabled = var.imageination_enabled
|
||||
name = "Image-ination"
|
||||
cost = "~$5/month"
|
||||
},
|
||||
{
|
||||
enabled = var.vmiam_enabled
|
||||
name = "VM I Am"
|
||||
cost = "~$15/month"
|
||||
},
|
||||
{
|
||||
enabled = var.cloudjumping_enabled
|
||||
name = "Cloud Jumping"
|
||||
cost = "~$15/month"
|
||||
}
|
||||
]
|
||||
|
||||
enabled_challenges = [
|
||||
for c in local.challenge_catalog :
|
||||
format("| | %-31s | %-12s |", c.name, c.cost)
|
||||
if c.enabled
|
||||
]
|
||||
}
|
||||
|
||||
output "Next_Steps" {
|
||||
value = <<EOT
|
||||
+---------
|
||||
|
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
| | Deployment Information: |
|
||||
| | |
|
||||
| | CloudFoxable deployed to: Subscription ${data.azurerm_client_config.current.subscription_id}|
|
||||
| | Tenant ${data.azurerm_client_config.current.tenant_id} |
|
||||
| | Scoreboard URL: https://cloudfoxable.bishopfox.com |
|
||||
| | CTF Starting User: Willem |
|
||||
| | Credentials: cat credentials.txt |
|
||||
| +---------------------------------------------------------------------------------------------+
|
||||
|
|
||||
| Next steps:
|
||||
|
|
||||
| 1. Access the credentials for your CTF user:
|
||||
|
|
||||
| cat credentials.txt
|
||||
|
|
||||
| 2. Logout your admin user:
|
||||
|
|
||||
| az logout
|
||||
|
|
||||
| 3. Verify your CTF user's credentials are working:
|
||||
|
|
||||
| az login
|
||||
|
|
||||
| 3. Head back to https://cloudfoxable.bishopfox.com and complete the first Azure challenge!
|
||||
|
|
||||
| You'll need this: FLAG{congrats_you_set_up_Terraform_with_Azure}
|
||||
|
|
||||
| +---------------------------------+---------------+
|
||||
| | Currently Enabled Challenges | Cost/Month |
|
||||
| +---------------------------------+---------------+
|
||||
${length(local.enabled_challenges) > 0 ? join("\n", local.enabled_challenges) : "| None | |"}
|
||||
| +-------------------------------------------------+
|
||||
|
|
||||
+---------
|
||||
EOT
|
||||
}
|
||||
|
||||
locals {
|
||||
credentials_text = <<-EOT
|
||||
client_id = ${azuread_user.ctf_user.user_principal_name}
|
||||
password = ${random_password.ctf_user_pw.result}
|
||||
EOT
|
||||
}
|
||||
|
||||
resource "local_file" "credentials" {
|
||||
filename = "credentials.txt"
|
||||
content = local.credentials_text
|
||||
file_permission = "0600"
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
######################
|
||||
# Azure Configuration
|
||||
######################
|
||||
|
||||
# Set your subscription_id
|
||||
subscription_id = ""
|
||||
|
||||
# Set the region to which to deploy resources. The default region is westus2
|
||||
# azure_region = ""
|
||||
|
||||
#######################
|
||||
# User Configuration
|
||||
#######################
|
||||
|
||||
# Use this variable to set the domain for your CTF users. You can find this by logging into Azure, going to Users, and looking at the domain name associated with the User Principal Name of your user account. For example: @johndoe.onmicrosoft.com
|
||||
domain = ""
|
||||
|
||||
#######################
|
||||
# User IP Configuration
|
||||
#######################
|
||||
|
||||
# Specify your IP address here to bre used with security groups (so that "public" challenges are only accessible to you)
|
||||
# If you don't specify anything, the default behavior is to use https://icanhazip.com to pull your IP address
|
||||
# user_ip = "[YOUR_IP_ADDRESS]"
|
||||
|
||||
############################
|
||||
# Enabled/Disabled Challenges
|
||||
############################
|
||||
|
||||
# enabled by default
|
||||
notsosecret_enabled = true
|
||||
permisery_enabled = true
|
||||
|
||||
# disabled by default (cost)
|
||||
imageination_enabled = false # about $5 per month / $0.17 per day
|
||||
vmiam_enabled = false # about $15 per month / $0.50 per day
|
||||
cloudjumping_enabled = false # about $15 per month / $0.50 per day
|
||||
@@ -0,0 +1,38 @@
|
||||
variable "azure_region" {
|
||||
description = "The Azure region to deploy to"
|
||||
type = string
|
||||
default = "westus2"
|
||||
}
|
||||
|
||||
variable "subscription_id" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "domain" {
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "notsosecret_enabled" {
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "permisery_enabled" {
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "imageination_enabled" {
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "vmiam_enabled" {
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "cloudjumping_enabled" {
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
Reference in new issue
Block a user