Enviar #1035481: Dianping (Meituan) CAT (Central Application Tracking), module `cat-home` (report web UI) 3.0.0 (released tag, same code path) and the 4.0-RC1 development line; reviewed at commit e815e74d4c2dd74edac831241f1253fcc7d25381 Cross-site scriptinginformación

TítuloDianping (Meituan) CAT (Central Application Tracking), module `cat-home` (report web UI) 3.0.0 (released tag, same code path) and the 4.0-RC1 development line; reviewed at commit e815e74d4c2dd74edac831241f1253fcc7d25381 Cross-site scripting
DescripciónUnauthenticated reflected XSS through the domain parameter of every CAT report page Vendor: Dianping (Meituan) Affected versions: 3.0.0 (released tag, same code path) and the 4.0-RC1 development line; reviewed at commit e815e74d4c2dd74edac831241f1253fcc7d25381 Vulnerability class: Cross-site scripting, reflected (CWE-79) Preconditions: none — anyone who can reach the deployment gets the page served anonymously under the shipped configuration. `PermissionFilter` (`system/page/permission/PermissionFilter.java:81-95`) bypasses authentication when `resourceConfigManager.getRole(requestURI, op)` returns `ResourceConfigManager.DEFAULT_RESOURCE_ROLE` (`ResourceConfigManager.java:44`, returned at `:87`); the shipped policy in `cat-home/src/main/resources/config/resource-config.xml` is only `<resource path="/r" op="view" role="2"/>`, whose key is the literal `/r` — a real request URI (`/cat/r/transaction`) never matches it, so the request is served as role 1 (anonymous). Confirmed at runtime with a cookie-less client. Unauthenticated reflected XSS through the domain parameter of every CAT report page Data flow: HTTP parameter `domain` → `AbstractReportPayload.java:54-55` → report handler/`Model.getDomain()` → `${model.domain}` unescaped in `WEB-INF/tags/hourlyReport.tag:104,116` / `historyReport.tag:103,116,120-129` (and page-level JSP duplicates) ### Affected interfaces | Interface | |---| | GET /cat/r/transaction?op=view&domain=<payload> — and every other report page (transaction, event, problem, heartbeat, cross, business, state, …) | | GET /cat/r/transaction?op=history&domain=<payload> — history mode of the same pages | Primary route detail: ``` GET /cat/r/<page>?op=view&domain=<payload> ``` Anonymous. The `domain` request parameter is the report-selection parameter of every CAT report page, meant to name a monitored project. It is bound verbatim and rendered by the shared report JSP tags with unescaped JSP EL inside HTML attributes, so a fully anonymous caller gets arbitrary HTML/JavaScript reflected 82 times in a `200 text/html` response and executed in the CAT origin (`value="…"><script>…` attribute breakout in `hourlyReport.tag:104`). ### Root cause 1. **Source** — `cat-core/src/main/java/com/dianping/cat/mvc/AbstractReportPayload.java:54-55`: `@FieldMeta("domain") private String m_domain = Constants.CAT;` binds the HTTP parameter verbatim (`setDomain`, `:188-192`, accepts every non-empty string). 2. **Flow** — `cat-home/src/main/java/com/dianping/cat/report/page/transaction/Handler.java:187-196` (`getHourlyReport`: `String domain = payload.getDomain();` at `:188`, wrapped into `new ModelRequest(domain, payload.getDate())` at `:194`) and attached to the page model (`Handler.java:238-242`, `:280`, `:286-293`, `:324`); the same pattern exists in the sibling report handlers. `report/page/transaction/Model.java:116-120` exposes the caller string again as `getDomain()`. 3. **Sink** — the shared report tags render the value unescaped inside HTML attributes: - `cat-home/src/main/webapp/WEB-INF/tags/hourlyReport.tag:104` — `<input id="search" type="text" value="${model.domain}" …>` (attribute breakout → script execution) - `hourlyReport.tag:116` — `<a class="switch" href="${model.baseUri}?op=history&domain=${model.domain}&ip=${model.ipAddress}">` - `historyReport.tag:103`, `:116`, `:120-129` (same value in `value=` / `href=`) - `hourlyStorageReport.tag:105`, `:117` and `historyStorageReport.tag:104` - page-level duplicates such as `jsp/report/transaction/transaction.jsp:11-12` (`title=...?domain=${model.domain}` / `navUrlPrefix="...domain=${model.domain}"`), `jsp/report/problem/problemHistoryReport.jsp:20-24`, `jsp/report/home/index.jsp:18-22`, `jsp/report/system.jsp:91`, `:149`. 4. **Missing guard** — no output escaping (`<c:out>`/JSTL/`fn:escapeXml`) on any of the above sinks, and no validation that `domain` is a valid domain name before it enters `ModelRequest`; additionally, the permission filter's literal `/r` policy key means the documented role policy never applies to real report URIs, leaving the reflection reachable anonymously. Baseline: commit `e815e74d4c2dd74edac831241f1253fcc7d25381`, `cat-home.war` built from source with Maven (sha256 `2152e10cdcdc1c2fafb2dd617755b0388e3e9bcc71306c9c9738bbc027e89107`), self-hosted instance on the reporter's own host on Tomcat 9.0.121 at `127.0.0.1:18808`, with a MySQL 8.4.11 instance. Harmless canary marker: `cv3cat9f31` / `CV3-CAT-XSS-9f31` (no payload that modifies server state). **1. Anonymous reflected XSS (view mode)** ```sh $ curl -s -i -G --data-urlencode 'domain=cv3cat9f31"><script>alert("CV3-CAT-XSS-9f31")</script>' \ 'http://127.0.0.1:18808/cat/r/transaction?op=view' HTTP/1.1 200 Set-Cookie: JSESSIONID=DA537DAC3DB0404923753D07FB1167BB; Path=/cat; HttpOnly Content-Type: text/html;charset=utf-8 raw payload occurrences in body: 82 value="cv3cat9f31"><script>alert("CV3-CAT-XSS-9f31")</script>" value="cv3cat9f31"><script>alert("CV3-CAT-XSS-9f31")</script>" class="search- ``` The rendered sink is the search box of the hourly report tag (`WEB-INF/tags/hourlyReport.tag:104`); the request sends no cookie, token or `Authorization` header (fresh `curl`, no session jar) — the response hands out a brand-new `JSESSIONID`, i.e. the reflection happens for an anonymous caller. **2. History-mode variant** — the same request with `op=history` reflects the payload 82 times through `WEB-INF/tags/historyReport.tag:103`. **3. Negative control** — the identical request with `domain=cat` returns the same page with **0** occurrences of `CV3-CAT-XSS-9f31`. - **Vendor contact**: GitHub Private Vulnerability Reporting - dianping/cat - **Status**: vendor notified 2026-10-06 through GitHub Private Vulnerability Reporting; private report <<GHSA_LINK>>; not publicly disclosed; no CVE assigned - **Duplicate check**: public advisories (NVD/OSV/GitHub) and the project issue tracker were searched before reporting; please tell us if this duplicates something already tracked internally.
Fuente⚠️ https://github.com/dianping/cat
Usuario
 lucasg2g (UID 84737)
Sumisión2026-10-15 07:30 (hace 24 días)
Moderación2026-11-08 11:50 (24 days later)
EstadoAceptado
Entrada de VulDB432810 [Dianping CAT 3.0.0/3.1.0/4.0-RC1 Report hourlyReport.tag Model.getDomain domain secuencias de comandos en sitios cruzados]
Puntos19

Do you know our Splunk app?

Download it now for free!