# Hacking a Bank by Finding a 0day in DotCMS

Unauthenticated dotCMS /api/content multipart upload uses unsanitized filename, enabling path traversal arbitrary file write and JSP webshell RCE.

- Payout: Research
- Severity: critical
- Program: DotCMS
- Credited: Assetnote
- Disclosed: 2024-01-31
- CVE: CVE-2022-26352
- Write-up quality: 8/10
- Original: https://www.assetnote.io/resources/research/hacking-a-bank-by-finding-a-0day-in-dotcms
- Library page: https://bugbountylibrary.com/r/blog%3Aassetnote-io-resources-research-hacking-a-bank-by-finding-a-0day-in-dotcms
- Tags: domain:web impact:integrity impact:rce kind:research platform:research sev:critical tech:java technique:chained technique:source-review vuln:file-upload vuln:path-traversal vuln:rce

**Target:** Java CMS REST API /api/content multipart upload endpoint
**Root cause:** processFile builds tempFile from user-controlled Content-Disposition filename without sanitization, and the endpoint allows anonymous WRITE access by default (CONTENT_APIS_ALLOW_ANONYMOUS=WRITE).
**Steps:**
1. Grep source for `@Path(` to map javax.ws.rs routes; find `com/dotcms/rest/ContentResource.java` with `@Path("/content")` and deprecated `multipartPOST`/`multipartPUT` accepting `/{params:.*}`
2. Confirm `.requiredAnonAccess(AnonymousAccess.WRITE)` and default `CONTENT_APIS_ALLOW_ANONYMOUS=WRITE`
3. Send `POST /api/content/` with `Content-Type: multipart/form-data` and a part `Content-Disposition: form-data; name="name"; filename="../../../../../../../../../srv/dotserver/tomcat-9.0.41/webapps/ROOT/html/js/dojo/a.jsp"` containing JSP shell
4. Request `https://target/html/js/dojo/a.jsp?cmd=whoami` to execute commands
5. Enumerate writable dirs via response fingerprinting: 500+empty body = success, distinct responses for nonexistent dir vs permission denied
6. Locate webroot via `/proc/self/cwd/../webapps/ROOT/html/`
7. If webroot unwritable, fetch a JS file's E-Tag and overwrite via `filename="../FIRST-CHAR/SECOND-CHAR/FULL-ETAG/fileAsset/FILE-NAME"`
**How found:** Whitebox audit: enumerated javax.ws.rs @Path routes, noticed ContentResource endpoints lacked auth, traced multipartPUTandPOST dispatch to sinks, ruled out XXE in processXML, then read processFile and spotted filename concatenated into File path with no validation.
**Exploitation:** Unauthenticated attacker posts multipart form to /api/content with traversal filename; server writes attacker bytes to arbitrary path. On dev, drop JSP webshell into Tomcat webapps/ROOT for RCE. On hardened bank, webroot unwritable, so attacker overwrote existing served JavaScript files by reconstructing their on-disk path from the E-Tag, achieving stored XSS/JS injection across 100+ assets.
**Escalation:** Chained arbitrary file write with webroot discovery via /proc/self/cwd and E-Tag-to-path reconstruction to overwrite served JS when direct webshell write was blocked.
**Insight:** When auditing Java CMS REST APIs, grep for `@Path(` to enumerate routes and check `requiredAnonAccess`/default config flags; then trace multipart `getFileName()` into `new File(...)` sinks. In hardened prod, use `/proc/self/cwd` to find webroot and E-Tag values to reconstruct on-disk paths of served static files for overwrite.
