FlawOpen

flawopen.com/Teardowns/cve-2026-14540-google-mcp-toolbox-ssrf

● CVE-2026-14540 · CVSS 8.0 · Tinggi
Riset Keamanan · FlawOpen

CVE-2026-14540: SSRF pada Google MCP Toolbox

CVE-2026-14540 membuat permintaan HTTP MCP Toolbox mengikuti pengalihan tanpa memeriksa tujuan jaringan akhirnya. Perbarui ke versi 1.5.0 atau yang lebih baru.[1], [3]

💡 Penjelasan Sederhana (ELI5)

Petugas sortir paket memeriksa alamat pertama, lalu mengikuti stiker penerusan tanpa memastikan alamat tujuan yang baru. Pengalihan HTTP seperti stiker itu: tanpa memeriksa IP akhir, permintaan untuk situs biasa dapat diteruskan ke jaringan privat. Perbaikan memeriksa tujuan sebenarnya saat koneksi dibuat dan juga memeriksa tujuan pengalihan.[2], [4], [7]

Konsep Kunci & Istilah

Server-side request forgery (SSRF)
Layanan dipengaruhi agar mengirim permintaan HTTP ke tujuan yang dikendalikan masukan penyerang. Karena permintaan berasal dari server, tujuannya dapat berada di jaringan yang tidak dapat dijangkau pemanggil.[6]
Pengalihan HTTP
Respons dapat meminta klien HTTP mengirim permintaan berikutnya ke URL lain. Memeriksa URL awal saja tidak membatasi tujuan permintaan lanjutan.[4], [7]
DNS rebinding dan TOCTOU
Nama host dapat resolve ke satu alamat saat validasi dan ke alamat lain saat socket dibuka. Memeriksa IP hasil resolusi ketika koneksi dibuat menutup celah antara pemeriksaan dan penggunaan.[2], [7]
Generic HTTP source dan tool
Komponen MCP Toolbox yang menyusun permintaan HTTP dari endpoint terkonfigurasi dan parameter tool. Advisory menyebut jalur ini sebagai bagian yang terdampak.[1], [2], [4]
CWE-918
Server-Side Request Forgery (SSRF): aplikasi mengambil URL atau menghubungi tujuan tanpa cukup membatasi ke mana permintaan boleh dikirim.[6]

Pemetaan kerangka kerja

Analisis Akar Masalah (Root Cause)

Pada versi terdampak, generic HTTP source membuat Go http.Client dengan timeout dan transport, tetapi tanpa kebijakan pengalihan yang memeriksa tujuan dan tanpa pembatasan IP di batas socket. Go mengikuti pengalihan secara default. Tool HTTP terkonfigurasi dapat memasukkan parameter ke permintaan, sehingga nilai yang dibuat khusus atau pengalihan dapat mengubah tujuan permintaan. Memeriksa URL awal saja tidak cukup: pengalihan mengubah tujuan dan DNS dapat mengembalikan IP berbeda antara validasi dan koneksi. Perbaikan upstream menambahkan SSRFGuard, menolak tujuan terblokir pada CheckRedirect, lalu memeriksa kembali IP hasil resolusi di lapisan koneksi. Alamat privat, loopback, link-local, dan alamat non-global lainnya diblokir secara default; izin rentang atau jaringan privat merupakan pengecualian konfigurasi yang harus dibatasi ketat.[1], [2], [4]

Alur Serangan Langkah demi Langkah

Langkah 1

Uji keterjangkauan dengan tiga kondisi

Rantai ini memerlukan ketiga kondisi berikut: (1) deployment terdampak versi 0.3.0–1.4.0 menggunakan generic HTTP source/tool; (2) pemanggil dapat menggunakan jalur itu dan mengendalikan URL/path atau memicu pengalihan; dan (3) host Toolbox dapat merutekan ke tujuan. Jika satu kondisi tidak terpenuhi, rantai ini tidak dapat mencapai tujuan melalui jalur tersebut. Autentikasi dan kontrol akses pada tujuan tetap berlaku.[1]

Langkah 2

Argumen tool memengaruhi permintaan keluar

HTTP tool terkonfigurasi menggabungkan endpoint dasar dengan nilai masukan. Deskripsi CVE menyebut parameter path yang dibuat khusus dapat mengarahkan HTTP source ke tujuan lain. Pengguna atau agent MCP memanggil tool; konten tidak tepercaya hanya memengaruhi panggilan jika workflow di sekitarnya memungkinkan.[1], [2]

Langkah 3

URL awal tidak membatasi pengalihan

Client terdampak tidak memiliki hook CheckRedirect yang membatasi dan tidak memvalidasi IP tujuan. Respons dapat menunjuk URL lain, jadi memeriksa endpoint dasar atau permintaan pertama saja tidak membatasi permintaan berikutnya.[1], [2]

Langkah 4

Toolbox meminta dari posisi jaringannya sendiri

Permintaan lanjutan berasal dari host Toolbox dan dapat menjangkau tujuan yang diizinkan oleh jaringan host tersebut. Layanan internal dapat menerima permintaan yang tidak dapat dikirim langsung oleh pemanggil MCP. CVE tidak membuktikan semua deployment mengekspos kredensial cloud atau semua pengalihan berhasil.[1]

Langkah 5

Perbarui dan verifikasi batas egress

Perbarui MCP Toolbox ke versi 1.5.0 atau lebih baru. Perbaikan memvalidasi IP literal yang dikonfigurasi, memeriksa tujuan pengalihan, dan memblokir IP hasil resolusi yang tidak diizinkan saat koneksi dibuat, termasuk untuk mencegah DNS rebinding. Biarkan allowPrivateNetworks nonaktif kecuali diperlukan; batasi rentang yang diizinkan dan terapkan kebijakan egress secara terpisah.[2], [3], [4]

Kode Sumber: Rentan vs Aman

Perbandingan ini adalah cuplikan terarah dari jalur client HTTP upstream, bukan pengganti seluruh file. Perbaikan yang digabung menambahkan SSRFGuard: guard memeriksa tujuan pengalihan dan menolak IP hasil resolusi yang diblokir saat koneksi dibuat, sehingga menutup celah DNS rebinding yang masih tersisa bila pemeriksaan hanya dilakukan saat pengalihan. Secara default guard memblokir alamat privat dan non-global lainnya. allowPrivateNetworks, allowedIpRanges, dan customBlockedIpRanges adalah kontrol yang kuat; pengecualian allowlist harus dibatasi hanya pada rentang yang diperlukan. File sumber: internal/sources/http/http.go.[2]

Cuplikan sumber: Cuplikan client HTTP dan kebijakan pengalihan

IMPLEMENTASI RENTAN
client := http.Client{
	Timeout: duration,
	Transport: tr,
}

// Tanpa kebijakan CheckRedirect, klien mengikuti pengalihan HTTP menggunakan
// kebijakan default. Transport juga tidak memiliki pelindung tujuan SSRF.
PERBAIKAN AMAN & KUAT
client := &http.Client{
	Timeout: duration,
	Transport: tr,
	CheckRedirect: func(req *http.Request, via []*http.Request) error {
		if len(via) >= 10 {
			return fmt.Errorf("stopped after 10 redirects")
		}
		hostname := req.URL.Hostname()
		if ip := net.ParseIP(hostname); ip != nil {
			if guard.IsIPBlocked(ip) {
				return fmt.Errorf("redirect to blocked IP %s denied", ip)
			}
			return nil
		}
		addrs, err := resolver.LookupHost(req.Context(), hostname)
		if err != nil {
			return fmt.Errorf("failed to resolve redirect host %s: %w", hostname, err)
		}
		for _, addr := range addrs {
			if ip := net.ParseIP(addr); ip != nil && guard.IsIPBlocked(ip) {
				return fmt.Errorf("redirect host %s resolves to blocked IP %s", hostname, addr)
			}
		}
		return nil
	},
}
// SSRFGuard yang sama juga diterapkan pada batas koneksi socket,
// sehingga jawaban DNS tidak dapat mengubah alamat yang diizinkan menjadi alamat yang diblokir.

Daftar Periksa Penguatan Sistem Rekayasa

Sumber