Merge pull request #37 from BishopFox/azure/new-challenges

Azure/new challenges
This commit is contained in:
Mitchell Cameron authored and GitHub committed 2026-05-01 14:21:57 -07:00
commit fc49b7f637
30 files changed
+2066 -1

No files matched your search

+11 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
1 Company Name Contact Name Phone Number Account Number
2 Moore, Williams and Howard Jeffrey Buck 001-329-531-9933x811 ACC9152546
3 Lamb LLC Mariah Taylor (688)284-2321 ACC7853737
4 Cooper Ltd Kaitlyn Hall 969-290-4235x36588 ACC4666894
5 Moore-Chung Johnathan Brown (160)022-9849x921 ACC6428594
6 Holmes, Cook and Nixon Daniel Leonard +1-142-448-4462x1756 ACC6443104
7 Hernandez PLC Ronnie Miller 275.701.5101 ACC3956160
8 Knox, Mcbride and Garcia Jose Roberts 001-584-829-8325 ACC3381547
9 Vargas-Miller Allen Fowler 496-091-4830x821 ACC1338965
10 Sutton-Giles Ms. Susan Mclaughlin MD 743-785-7819 ACC8305704
11 Rogers, Goodman and Walker Nicole Lewis 919-646-3100x86195 ACC1351042
12 Russo-Jackson Brandy Bowen +1-486-787-3249x1474 ACC8364973
13 Johnson LLC Dana Taylor 759.028.9938 ACC1059913
14 King-Perez David Aguilar (272)705-1445 ACC3569283
15 Hamilton PLC James Walsh (672)140-8866 ACC9003263
16 Stein, Mann and Hicks Jason Alvarez 001-604-568-2923x04241 ACC5671035
17 Burton-Freeman Francisco Barnett (649)166-9393 ACC6599375
18 Petersen-Khan Toni Waller +1-433-248-9279x5276 ACC6968903
19 Lewis-Beard Shirley Davis 3960557191 ACC8168304
20 Thomas, Coleman and Sparks Christopher Bailey +1-444-237-3667x3736 ACC7435431
21 Singh LLC Christopher White 341.198.4207x1101 ACC3963195
22 Pham Inc Tracy Farmer (076)208-5346x5097 ACC1046678
23 Hernandez, Morrison and Duncan Dominique Huang 686-944-1314x67632 ACC3957320
24 Gilbert-Meyer Derek Curry 475.931.1530x4987 ACC5986477
25 Fleming PLC Daniel Hughes MD 639.490.9675 ACC6509178
26 Aguirre-Frey Michael Singh (691)077-4246x1917 ACC4565589
27 Hurley, Rodriguez and Rodriguez Morgan Sanders 077-522-1436x3793 ACC8308658
28 Lee, Patel and Nelson Dennis Melendez +1-238-174-3567x551 ACC9522388
29 Medina-Burns Meghan Sanders (201)220-6129 ACC5453422
30 Floyd and Sons Curtis Mccarthy (204)365-8350x65420 ACC3920241
31 Duran Inc Jasmine Stephens 988-261-9650x97646 ACC9777507
32 Brown, West and Lane Daniel Hamilton (836)570-0594 ACC1611446
33 Gonzalez, Hoffman and Walker Denise Smith 723-231-9986x02347 ACC5409826
34 Allen LLC Matthew Wallace 416-688-9957x1041 ACC5244411
35 Holder Group Andrea Hicks 708.401.2880x3317 ACC9684757
36 Burns-Harris Gregory Garner 8717086592 ACC3243985
37 Burns and Sons Christine Hill 600.992.7003 ACC5939428
38 Martin Group Michelle Davis 875.132.3763x04584 ACC6236484
39 Baker-Campbell Ralph Decker +1-071-070-0191x208 ACC4704261
40 Henry, Vasquez and Blackwell Kim Fuller 092.916.9672 ACC7815217
41 Owens, Taylor and Morgan Lisa Roth 0408349918 ACC8013568
42 Griffith, Weaver and Payne Richard Boone 001-811-295-5742x71145 ACC3869952
43 Jones, Harris and Figueroa Chelsea Mcdaniel 001-817-091-0223 ACC1097157
44 Garcia, Trujillo and Carpenter Wendy Bailey 1319801073 ACC2095110
45 White Ltd Brian Cole 846-143-0853 ACC1078744
46 Flores Inc Madison Strickland +1-211-796-4471 ACC5288837
47 Tucker, Valencia and Rivera Jaime Clark 471-220-0871x85925 ACC4047815
48 Rodriguez, Vega and Bishop Melanie Reynolds (641)602-7556 ACC7848165
49 Goodwin-Colon Nancy Richardson 720-800-1277x6554 ACC5134045
50 Rodriguez Ltd Jennifer Williams (578)134-1303x31096 ACC0861327
51 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
View File
@@ -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
1 Firstname Lastname email Hiredate
2 Madeline Gibson [email protected] 2023-11-21
3 Cody Thompson [email protected] 2022-02-24
4 Jeremy Barton [email protected] 2021-02-07
5 Sheri Mcknight [email protected] 2022-12-11
6 Jessica Ray [email protected] 2023-05-15
7 Kevin Wells [email protected] 2024-04-27
8 Michael Harris [email protected] 2022-08-24
9 Sandra Pierce [email protected] 2023-08-12
10 Veronica Arnold [email protected] 2022-07-26
11 Sharon Gomez [email protected] 2023-04-10
12 Grace Wong [email protected] 2020-04-24
13 Kim Estrada [email protected] 2023-05-22
14 Laura Clayton [email protected] 2021-06-27
15 Paul Robinson [email protected] 2021-12-12
16 Matthew Smith [email protected] 2022-05-08
17 Anita Cruz [email protected] 2022-01-09
18 Tyler Turner [email protected] 2021-12-08
19 David Branch [email protected] 2021-11-16
20 Gregory Ayala [email protected] 2022-02-28
21 Alexander Jensen [email protected] 2021-03-12
22 Cheryl Payne [email protected] 2022-02-13
23 Marie Hood [email protected] 2023-06-12
24 Michael Yang [email protected] 2021-08-06
25 Tiffany Jordan [email protected] 2024-12-27
26 Michelle Brown [email protected] 2022-05-03
27 Allison Alvarado [email protected] 2024-05-17
28 Janet Freeman [email protected] 2023-12-19
29 Jason Mclaughlin [email protected] 2024-10-17
30 Scott Garcia [email protected] 2022-12-13
31 Sean Moreno [email protected] 2022-12-16
32 Matthew Smith [email protected] 2021-09-14
33 Jasmine Anderson [email protected] 2021-10-15
34 Ryan Campbell [email protected] 2024-10-19
35 Lisa Patterson [email protected] 2024-09-30
36 Scott Hardy [email protected] 2020-07-25
37 Gregory Johnson [email protected] 2020-05-01
38 Scott Collins [email protected] 2021-02-22
39 Amanda Hall [email protected] 2022-05-06
40 Mary Russell [email protected] 2021-08-13
41 Devon Becker [email protected] 2022-09-19
42 Jorge Lutz [email protected] 2020-04-29
43 Gabriel Jones [email protected] 2023-07-14
44 Gary Waters [email protected] 2022-02-28
45 Amy Zavala [email protected] 2021-05-31
46 Michael Solis [email protected] 2021-11-19
47 Kenneth Trujillo [email protected] 2022-07-20
48 Suzanne Marsh [email protected] 2020-08-02
49 Bryan Peters [email protected] 2024-12-28
50 Patricia Oneal [email protected] 2022-02-04
51 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
View File
@@ -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
}
+232
View File
@@ -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]
}
+11
View File
@@ -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" ]
+11
View File
@@ -0,0 +1,11 @@
variable "azure_region" {
type = string
}
variable "player_upn" {
type = string
}
variable "player_object_id" {
type = string
}
+234
View File
@@ -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
View File
@@ -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"
}
+37
View File
@@ -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
+38
View File
@@ -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
}