
بروميثيوس v3.15.0 - عالية - عن بُعد - SSRF - http_sd __unix_socket__ Dial غير معقّم متبقٍ من كشط UDS
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · prometheus-unix-socket-dial
الفئة: SSRF الوصول: عن بُعد
Prometheus v3.15.0 (5241a27) - CNCF / Prometheus
أضاف الإصدار v3.15.0 جلب Unix Domain Socket (#12024 / #18091). المسار هو وسم هدف __unix_socket__، وليس قائمة سماح للمشغّل. ينسخ http_sd و file_sd ذلك الوسم كما هو. لا يتحقق PopulateLabels منه أبدًا. ثم يستدعي newUnixSocketScrapeClient الدالة DialContext(ctx, "unix", socketPath) دون filepath.Clean، ودون قائمة سماح، ودون رفض ../ أو أسماء Linux المجرّدة @.
لا يمكن لجلب TCP فعل ذلك. لا يزال CheckTargetAddress يُسقط قيم __address__ التي تحتوي على /، لذا يُرفض unix:///var/run/docker.sock كعنوان. الوسم الجديد هو الثغرة.
لا يضبط الإعداد الافتراضي الوسم. لا يمكن لـ HTTP غير المُصادَق إلى Prometheus إضافة مهام. هذا مقيّد بـ SD.
| المعرّف | لا يوجد CVE بعد |
| الفئة | SSRF (استدعاء unix Dial غير مُعقّم من وسوم SD) |
| الوصول | عن بُعد (مقيّد بـ SD: كاتب http_sd / file_sd) |
| CWE | CWE-918، CWE-22 |
| CVSS | مرتفع: 8.6 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N |
| المنتج | Prometheus |
| المتأثر | v3.15.0 (5241a27fe3c6983549fccc32f6e65917408c63cd)، الصورة prom/prometheus:v3.15.0 |
| المصادقة | مقيّد بـ SD: كاتب وسوم http_sd / file_sd (أو relabel ينسخ بيانات وصفية غير موثوقة إلى __unix_socket__) |
| الترخيص | GNU Affero GPL v3.0 |
| المختبر | 127.0.0.1 فقط |
التحكم في JSON الخاص بـ http_sd (أو file_sd القابل للكتابة) كافٍ. رابط SD هو إعداد المشغّل. ما يتبقى هو أن labels الخاصة بالمجموعة قد تضبط __unix_socket__ وسيقوم Prometheus باستدعائه.
| الصلاحية | الطريقة / نقطة الوصول | مُثبت مختبريًا أو مُستنتج |
|---|---|---|
| الاتصال بـ unix socket على المضيف يمكن لمستخدم Prometheus فتحه | clientForTarget -> DialContext(ctx, "unix", socketPath) من __unix_socket__ | مُثبت مختبريًا. المسار /sockets/jail/../oracle.sock من http_sd؛ صحة الجلب up |
اتباع ../ في ذلك المسار | لا filepath.Clean / لا رفض .. | مُثبت مختبريًا. حلّت النواة العبور إلى /sockets/oracle.sock |
| استدعاء Linux abstract socket | نفس Dial لـ @name | مُثبت مختبريًا. __unix_socket__=@prom-lab-oracle؛ صحة الجلب up |
| HTTP GET على ذلك الـ socket بهوية مستخدم Prometheus | الجلب هو GET؛ __metrics_path__ هو مسار الطلب | مُثبت مختبريًا. GET /fs-traversal و /abstract؛ User-Agent Prometheus/؛ تم إدخال lab_witness |
| الوصول إلى sockets لا يمكن لجلب TCP تسميتها | يرفض CheckTargetAddress وجود / في __address__ | مُثبت مختبريًا. unix:///var/run/docker.sock كـ __address__ سجّل is not a valid hostname؛ ليس هدفًا نشطًا؛ prometheus_target_sync_failed_total=1 |
| GET على واجهات Docker Engine / kubelet HTTP إذا كانت تلك الـ sockets في النطاق | __unix_socket__=/var/run/docker.sock مع مسار Docker API | مُستنتج. نفس Dial غير المُعقّم. لا يُركّب هذا المختبر socket محرك حقيقي. عادةً تفشل واجهات JSON في تحليل العرض، لذا فإن الخطورة المرتفعة هي الاتصال/GET، وليس استخراج TSDB لـ Docker JSON |
| تعديل Docker (إنشاء حاوية، كتابة) | أفعال الجلب | مغلق. الجلب هو GET فقط |
| إضافة مهام جلب عبر HTTP غير المُصادَق لـ Prometheus | /-/reload، admin API | مغلق. كلا العَلَمين معطّل افتراضيًا؛ reload ليس له جسم |
| استخدام هذا على إعداد المثال الافتراضي | __unix_socket__ غير مضبوط؛ المثال يجلب localhost:9090 عبر TCP | مغلق. تُصدر SD المدمجة k8s/consul/docker __meta_* فقط؛ تُحذف تلك البادئات بعد relabel |
نموذج أمان المورّد يسمح بالفعل لـ SD باختيار أهداف جلب TCP. البدائية الجديدة هي IPC على المضيف لم يستطع __address__ تسميته.
ثبّتت prometheus/prometheus v3.15.0 بعد سطر ميزة 3.15 لجلب UDS. الإعداد الافتراضي مفتوح المصدر على هذا التثبيت يُعطّل admin API، وlifecycle HTTP، ومستقبل remote-write، ومستقبل OTLP. ينسخ PopulateDiscoveredLabels كل وسم مجموعة http_sd. __unix_socket__ ليس __meta_*، لذا ينجو من محو البيانات الوصفية. يتحقق PopulateLabels من __address__ فقط.
func (sp *scrapePool) clientForTarget(t *Target) *http.Client {
socketPath := t.labels.Get(UnixSocketLabel)
if socketPath == "" {
return sp.client
}
client, err := newUnixSocketScrapeClient(socketPath, ...)
func newUnixSocketScrapeClient(socketPath string, ...) (*http.Client, error) {
optFuncs = append([]config_util.HTTPClientOption{config_util.WithDialContextFunc(
func(ctx context.Context, _, _ string) (net.Conn, error) {
return (&net.Dialer{}).DialContext(ctx, "unix", socketPath)
},
)}, optFuncs...)
لا يزال CheckTargetAddress يرفض / في العنوان. يحتفظ URL() بالمخطط/المضيف/المسار من __scheme__ / __address__ / __metrics_path__؛ الـ socket للاستدعاء فقط.
المنعطفات الخاطئة المسجّلة مسبقًا: تصنيف هذا كـ NONE ضمن النموذج لأن SD يختار بالفعل أهداف TCP (البدائية الجديدة هي IPC على المضيف)؛ اعتبار unix:///var/run/docker.sock كـ __address__ هو الثغرة (إنه مرفوض)؛ الادعاء بأن إعداد المثال الافتراضي هو هذا المتبقي. المسرحية: reverse shell. الأوراكل هو صحة الجلب up على sockets سمّاها SD JSON.
python3 prometheus-unix-socket-dial-Abraxas-Labs.py
أو
cd lab
./run.sh
يتشارك prom/prometheus:v3.15.0 netns مع sidecar بلغة Python. يقدّم الـ sidecar http_sd على 127.0.0.1:8080/targets.json وأوراكلَي unix HTTP: نظام الملفات /sockets/oracle.sock والمجرّد @prom-lab-oracle. يُنشر Prometheus على 127.0.0.1:19390. يبقى admin API وlifecycle معطّلين.
SUCCESS prometheus-unix-socket-dial sd=http_sd fs-traversal=yes abstract=yes tcp-slash-rejected=yes how=sd-labels PROMETHEUS-UNIX-SOCKET-DIAL-WITNESS
مؤشر الاختراق: scrapeUrl=http://localhost:1/fs-traversal و /abstract، كلاهما بحالة up. لم يصبح TCP slash هدفًا نشطًا أبدًا.
لا تستدعِ __unix_socket__ من SD حتى يصبح مسار نظام ملفات مطلقًا ومُعقّمًا. ارفض القيم الفارغة، وNUL، وأسماء Linux المجرّدة @، والمسارات النسبية، وأي .. بعد filepath.Clean. قائمة سماح بالبادئات من scrape YAML أقوى. كما أن إسقاط الوسم من PopulateDiscoveredLabels ما لم يأتِ من إعداد المشغّل يُغلق حقن SD.
5241a27fe3c6983549fccc32f6e65917408c63cd)scrape/scrape.go · scrape/target.go · config/config.goGNU Affero GPL v3.0. انظر LICENSE. مختبر loopback فقط. لا ضمان.