Skip to content

DoraCMS 3.1 Security Report SSRF (Responsible Disclosure) #268

@13ernkastel

Description

@13ernkastel

DoraCMS 3.1 Security Report (Responsible Disclosure)

Report Title: SSRF via UEditor Remote Image Fetch (catcher/catchImage)
Product: DoraCMS 3.1
Date: 2026-02-10

Scope: Source-code review of DoraCMS 3.1 server-side codebase


1. Executive Summary

DoraCMS 3.1 includes a Server-Side Request Forgery (SSRF) weakness in its UEditor integration. DoraCMS exposes UEditor endpoints under the upload module, and the UEditor “remote image catcher” action triggers server-side fetching of user-supplied URLs via http.request / https.request without destination restrictions (no allowlist, no private-IP blocking) or resource safety controls (no timeout, no max response size, no redirect policy).

If reachable by untrusted users, this enables attackers to induce the DoraCMS server to make outbound requests to arbitrary destinations, potentially including internal services. Additionally, the implementation buffers remote responses into memory and writes the fetched content into a public upload directory, increasing potential impact and enabling denial-of-service conditions.


2. Context: UEditor in DoraCMS is used for File Upload

DoraCMS integrates UEditor as part of its file upload functionality. This is evident from server/app/router/api/v1.js, where UEditor routes are grouped under the file upload section and are handled by the same uploadFile controller used for upload endpoints.

Evidence (Source Code)

File: server/app/router/api/v1.js

// ==================== 文件上传 ====================
router.post('/api/v1/files', authApiToken, controller.api.uploadFile.create);
router.post('/api/v1/files/path', authApiToken, controller.api.uploadFile.createFileByPath);
router.get('/api/v1/upload/ueditor', controller.api.uploadFile.ueditor);
router.post('/api/v1/upload/ueditor', controller.api.uploadFile.ueditor);

Explanation

  • The comment // ==================== 文件上传 ==================== groups these routes under DoraCMS’ upload module.
  • /api/v1/files and /api/v1/files/path are authenticated upload routes.
  • /api/v1/upload/ueditor (GET/POST) is mapped to controller.api.uploadFile.ueditor within the same upload grouping, demonstrating that UEditor is part of DoraCMS’ upload implementation.

3. Vulnerability Overview

3.1 Title

Server-Side Request Forgery (SSRF) via UEditor Remote Image Fetch (catchImage)

3.2 Severity

High

3.3 OWASP Mapping

  • OWASP Top 10 (2021): A10 – Server-Side Request Forgery (SSRF)
  • Secondary: A05 – Security Misconfiguration (if endpoint is publicly reachable; depends on deployment)

3.4 Affected Versions

  • Confirmed in DoraCMS 3.1 (source-level confirmation)

4. Affected Endpoints & Components

4.1 Routes

File: server/app/router/api/v1.js

  • GET /api/v1/upload/ueditor
  • POST /api/v1/upload/ueditor

Note: These UEditor routes are not protected by authApiToken in v1.js, unlike /api/v1/files and /api/v1/files/path. If there is no other global authorization layer, exposure increases.

4.2 Vulnerable Function

File: server/app/controller/api/uploadFile.js
Function: catchImage(url)

Observed behaviors (high-level):

  • Accepts a URL derived from client input.
  • Performs server-side HTTP(S) request using the provided URL.
  • Buffers the full response body into memory as base64.
  • Returns content that is then saved to the public upload directory.

5. Technical Details

5.1 Root Cause

Untrusted input (a remote URL) is used directly in server-side HTTP request functions without:

  • destination allowlisting,
  • private/internal IP range blocking,
  • redirect controls,
  • timeouts,
  • response size limits.

This creates an SSRF request primitive.

5.2 Code Evidence (Request Primitive)

File: server/app/controller/api/uploadFile.js (approx. lines 67–96)

const request = /^https:\/\//.test(url) ? https.request : http.request;
const req = request(url, res => {
  res.setEncoding('base64');
  res.on('data', chunk => { base64Data += chunk; });
  res.on('end', () => resolve({ contentType, base64Data, originalname }));
});
req.on('error', () => resolve({ error: true }));
req.end();

Key security gaps:

  • No URL parsing and validation using new URL()
  • No allowlist of domains/hosts
  • No checks against RFC1918 / loopback / link-local ranges
  • No DNS rebind defense
  • No timeout on requests
  • No max download size (unbounded base64Data += chunk)
  • No redirect policy

5.3 Call Chain (UEditor “remote catcher” action)

File: server/app/controller/api/uploadFile.js
Method: ueditor()

When the action corresponds to the UEditor remote image catcher action, DoraCMS reads URLs from the request and calls catchImage() for each URL. The returned base64 data is then written into the public directory via upload.base64Image(...).

High-level flow:

  1. Router routes request to controller.api.uploadFile.ueditor
  2. ueditor() checks ctx.query.action
  3. For the catcher action:
    • reads a list of URLs from ctx.request.body[...]
    • calls catchImage(url) for each
    • persists fetched content to a public directory
    • returns a JSON list of results

6. Impact Assessment

Depending on deployment environment and network configuration, this SSRF weakness can enable:

  1. Outbound request to attacker-chosen destinations

    • The server becomes an HTTP client to arbitrary URLs supplied by the requester.
  2. Access to internal-only services (pivoting)

    • Requests can potentially reach internal hosts/services not accessible externally.
  3. Potential data exposure through persisted content (environment dependent)

    • Responses are buffered and saved under the upload directory; if an internal service returns sensitive content in a way that passes downstream checks, data may be written to disk.
  4. Denial of Service

    • Lack of timeout and response-size limit can cause:
      • hanging sockets / connection exhaustion,
      • memory growth from unbounded base64 buffering,
      • server resource exhaustion.

7. Reproduction / Verification (Safe Guidance)

To validate in an authorized test environment without targeting internal networks:

  1. Stand up an HTTP endpoint you control (e.g., a small logging server) that records inbound requests.
  2. Invoke /api/v1/upload/ueditor with the UEditor “remote catcher” action and provide your controlled URL in the expected request-body field.
  3. Confirm the controlled endpoint receives a request originating from the DoraCMS server.
  4. Confirm DoraCMS returns success and that a file is created in the public upload directory (depending on configuration and whether the endpoint stores results).

This demonstrates that DoraCMS performs server-side outbound fetching based on user-provided URLs.


8. Recommendations

8.1 Preferred: Allowlist of Trusted Hosts

  • Restrict remote fetching to a known set of domains (e.g., your CDN or approved image hosts).
  • Reject IP-literal URLs unless explicitly required.

9. External Reference (Similar Vulnerability Class)

This issue matches a well-known SSRF pattern in UEditor “catchimage/catcher” implementations, similar in class to:

(Reference provided for context; DoraCMS codebase has its own independent SSRF primitive as documented above.)


End of Report

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions