Hey there! I'm currently a bit swamped with this Azure deployment.
Once I'm done I'll tell you about it. It's pretty awesome!
You'll need a bit of Azure knowledge though. Sparkle Redberry can help you get up to speed on that. You can find her at the Rudolph's Rest Resort on Christmas Island.
After solving the objective Azure 101 from Sparkle Redberry:
Hello there! Alabaster Snowball at your service.
I could use your help with my fancy new Azure server at ssh-server-vm.santaworkshopgeeseislands.org.
ChatNPT suggested I upgrade the host to use SSH certificates, such a great idea!
It even generated ready-to-deploy code for an Azure Function App so elves can request their own certificates. What a timesaver!
I'm a little wary though. I'd appreciate it if you could take a peek and confirm everything's secure before I deploy this configuration to all the Geese Islands servers.
Generate yourself a certificate and use the monitor account to access the host. See if you can grab my TODO list.
If you haven't heard of SSH certificates, Thomas Bouve gave an introductory talk and demo on that topic recently.
Oh, and if you need to peek at the Function App code, there's a handy Azure REST API endpoint which will give you details about how the Function App is deployed.
Alabaster Snowball gives you following hints as well:
Check out Thomas Bouve's talk and demo to learn all about how you can upgrade your SSH server configuration to leverage SSH certificates.
The get-source-control Azure REST API endpoint provides details about where an Azure Web App or Function App is deployed from.
Firstly, let's watch the video here to understand how SSH certificates work.
PROMPT: Can you give me a short explanation how SSH certificates work ?
ChatGPT:
In a typical SSH setup without certificates, users authenticate themselves to a server using a pair of cryptographic keys: a public key and a private key. The server must have a copy of the user's public key in advance (usually in the ~/.ssh/authorized_keys
file), and the user must possess the corresponding private key.
SSH certificates introduce a Certificate Authority (CA) into this process. Instead of directly trusting individual public keys, the server is configured to trust the CA. The CA issues certificates that vouch for the identity of users or hosts.
The CA signs a user's or host's public key along with identity information (like usernames or hostnames) to create an SSH certificate. This process is similar to how SSL certificates are issued for websites.
When a user connects to a server, instead of providing their public key for verification, they present their SSH certificate. The server, trusting the CA, verifies the signature on the certificate using the CA's public key. If the certificate is valid, the user is authenticated.
Similarly, SSH certificates can be used to authenticate the server to the user's client, ensuring the client is connecting to the legitimate server.
So the first thing we do is generate an SSH key pair
user@machine:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa
Your public key has been saved in /home/user/.ssh/id_rsa.pub
...
Next, we navigate to the application mentioned at https://northpole-ssh-certs-fa.azurewebsites.net/api/create-cert?code=candy-cane-twirl and copy our public key /home/user/.ssh/id_rsa.pub
into it.
We will then receive an SSH certificate back (which is our signed public SSH key).
Alabaster Snowball mentioned to use the monitor account to access the host. Let's use our new SSH certifcate:
mv ssh_cert.txt .ssh/id_rsa.pub
We can see an Satellite Tracking Interface
which we'll cancel by pressing CTRL-C
.
The next step is to access the Web Apps - Get Source Control see Microsoft's documentation here.
To make it easier we're using Postman. We want to send a GET request to https://management.azure.com/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroupName}}/providers/Microsoft.Web/sites/{{name}}/sourcecontrols/web?api-version=2022-03-01.
We set an environment like this (the values can be taken from the previous objective Azure 101:
We submit the request and get
{
"error": {
"code": "AuthenticationFailed",
"message": "Authentication failed. The 'Authorization' header is missing."
}
}
Let's quickly ask the AI:
PROMPT: I do have access to Azure via CLI and can use "az account show" to access account information. Now I want to access the API but I get an error message "The Authorization header is missing." How can I use the working CLI to access the API as well?
ChatGPT:
To access Azure APIs using the credentials from your Azure CLI, you need to obtain an access token that you can use as the Authorization header in your API requests. Here's a step-by-step guide on how to do this:
You can obtain an access token by using the Azure CLI command az account get-access-token
. This command will return a JSON object that includes an accessToken field.
When making API calls to Azure services, you need to include this access token in the Authorization header. The header should look like: Authorization: Bearer <accesstoken>
, where <accesstoken>
is the token you obtained from the Azure CLI.
Too bad we don't have enough permissions in the former Objective Azure 101. But we already have SSH access to the target VM. We remember the last KringleCon 2022 and the metadata, more information can be found here. Let's try it out right away.
monitor@ssh-server-vm:~$ curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -H Metadata:true -s
{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGc........WRQjIw","client_id":"b84e06d3-aba1-4bcc-9626-2e0d76cba2ce","expires_in":"83831","expires_on":"1702162535","ext_expires_in":"86399","not_before":"1702075835","resource":"https://management.azure.com/","token_type":"Bearer"}monitor@ssh-server-vm:~$
We copy the value of the access_token
over to Postman and send the request again.
We found the repository after all: https://github.com/SantaWorkshopGeeseIslandsDevOps/northpole-ssh-certs-fa
We want to change the principal to get more permissions. So let's take a look at the source code to see if there is a possibility there. In fact, the code accepts an additional parameter principal, which is not used in the web page.
if not (ssh_pub_key.lower().startswith("ssh-rsa") or ssh_pub_key.lower().startswith("ssh-ed25519")):
raise ValidationError("ssh_pub_key is not an RSA or ED25519 SSH public key.")
principal = data.get("principal", DEFAULT_PRINCIPAL)
if not isinstance(principal, str):
raise ValidationError("principal is not a string.")
So let's send the same request via Burp Suite and then send it to the repeater. There we simply add the parameter and send the request again. And the response does indeed contain the spoofed principal.
We now use the new SSH public key and can use it to log in as Alabaster.
And that gives us the solution.
Alabaster Snowball tells us
Oh my! I was so focused on the SSH configuration I completely missed the vulnerability in the Azure Function App.
Why would ChatNPT generate code with such a glaring vulnerability? It's almost like it wanted my system to be unsafe. Could ChatNPT be evil?
Thanks for the help, I'll go and update the application code immediately!
While we're on the topic of certificates, did you know Active Directory (AD) uses them as well? Apparently the service used to manage them can have misconfigurations too.
You might be wondering about that SatTrackr tool I've installed on the monitor account?
Here's the thing, on my nightly stargazing adventures I started noticing the same satellite above Geese Islands.
I wrote that satellite tracker tool to collect some additional data and sure enough, it's in a geostationary orbit above us.
No idea what that means yet, but I'm keeping a close eye on that thing!
And we get a new hint:
Certificates are everywhere. Did you know Active Directory (AD) uses certificates as well? Apparently the service used to manage them can have misconfigurations too.